3165 lines
124 KiB
C++
3165 lines
124 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 SHARE
|
|
#include "share/system_variable/ob_system_variable_factory.h"
|
|
#include "share/system_variable/ob_system_variable.h"
|
|
#include "share/system_variable/ob_system_variable_alias.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
#include "sql/engine/ob_exec_context.h"
|
|
#include "share/inner_table/ob_inner_table_schema.h"
|
|
#include "share/ob_time_zone_info_manager.h"
|
|
#include "lib/oblog/ob_log.h"
|
|
#include "lib/number/ob_number_v2.h"
|
|
#include "common/sql_mode/ob_sql_mode.h"
|
|
#include "share/ob_version.h"
|
|
#include "lib/utility/utility.h"
|
|
#include "common/sql_mode/ob_sql_mode_utils.h"
|
|
#include "share/ob_common_rpc_proxy.h"
|
|
#include "sql/ob_sql_utils.h"
|
|
#include "share/object/ob_obj_cast.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "storage/tx/ob_trans_define.h"
|
|
#include "storage/tx/ob_trans_service.h"
|
|
#include "observer/omt/ob_tenant_timezone_mgr.h"
|
|
#include "ob_nls_system_variable.h"
|
|
#include "sql/engine/expr/ob_expr_plsql_variable.h"
|
|
#include "share/resource_manager/ob_resource_manager_proxy.h"
|
|
#include "sql/engine/expr/ob_expr_uuid.h"
|
|
#ifdef OB_BUILD_ORACLE_PL
|
|
#include "pl/ob_pl_warning.h"
|
|
#endif
|
|
|
|
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::share;
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
using namespace sql;
|
|
using namespace transaction;
|
|
namespace share
|
|
{
|
|
char ObSpecialSysVarValues::version_comment_[ObSpecialSysVarValues::VERSION_COMMENT_MAX_LEN];
|
|
char ObSpecialSysVarValues::version_[ObSpecialSysVarValues::VERSION_MAX_LEN];
|
|
char ObSpecialSysVarValues::system_time_zone_str_[ObSpecialSysVarValues::SYSTEM_TIME_ZONE_MAX_LEN];
|
|
char ObSpecialSysVarValues::default_coll_int_str_[ObSpecialSysVarValues::COLL_INT_STR_MAX_LEN];
|
|
char ObSpecialSysVarValues::server_uuid_[ObSpecialSysVarValues::SERVER_UUID_MAX_LEN];
|
|
|
|
ObSpecialSysVarValues::ObSpecialSysVarValues()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t pos = 0;
|
|
// OB_SV_VERSION_COMMENT
|
|
if (OB_FAIL(ret)) {
|
|
} else if (FALSE_IT(pos = 0)) {
|
|
} else if (OB_FAIL(databuff_printf(ObSpecialSysVarValues::version_comment_,
|
|
ObSpecialSysVarValues::VERSION_COMMENT_MAX_LEN,
|
|
pos,
|
|
#ifdef OB_BUILD_CLOSE_MODULES
|
|
"OceanBase %s (r%s) (Built %s %s)",
|
|
#else
|
|
"OceanBase_CE %s (r%s) (Built %s %s)",
|
|
|
|
#endif
|
|
PACKAGE_VERSION, build_version(),
|
|
build_date(), build_time()))) {
|
|
LOG_ERROR("fail to print version_comment to buff", K(ret));
|
|
}
|
|
|
|
// OB_SV_VERSION
|
|
if (OB_FAIL(ret)) {
|
|
} else if (FALSE_IT(pos = 0)) {
|
|
} else if (OB_FAIL(databuff_printf(ObSpecialSysVarValues::version_,
|
|
ObSpecialSysVarValues::VERSION_MAX_LEN,
|
|
#ifdef OB_BUILD_CLOSE_MODULES
|
|
pos, "5.7.25-OceanBase-v%s", PACKAGE_VERSION))) {
|
|
#else
|
|
pos, "5.7.25-OceanBase_CE-v%s", PACKAGE_VERSION))) {
|
|
|
|
#endif
|
|
LOG_ERROR("fail to print version to buff", K(ret));
|
|
}
|
|
|
|
// OB_SV_SYSTEM_TIME_ZONE
|
|
if (OB_SUCC(ret)) {
|
|
pos = 0;
|
|
tzset(); // init tzname
|
|
int64_t current_time_us = ObTimeUtility::current_time();
|
|
struct tm tmp_tm;
|
|
UNUSED(localtime_r(¤t_time_us, &tmp_tm));
|
|
bool is_neg = false;
|
|
if (tmp_tm.tm_gmtoff < 0) {
|
|
is_neg = true;
|
|
tmp_tm.tm_gmtoff = 0 - tmp_tm.tm_gmtoff;
|
|
}
|
|
const int64_t tz_hour = tmp_tm.tm_gmtoff / 3600;
|
|
const int64_t tz_minuts = (tmp_tm.tm_gmtoff % 3600) % 60;
|
|
if (OB_FAIL(databuff_printf(ObSpecialSysVarValues::system_time_zone_str_,
|
|
ObSpecialSysVarValues::SYSTEM_TIME_ZONE_MAX_LEN,
|
|
pos,
|
|
"%s%02ld:%02ld",
|
|
(is_neg ? "-" : "+"),
|
|
tz_hour,
|
|
tz_minuts))) {
|
|
LOG_ERROR("fail to print system_time_zone to buff", K(ret), K(is_neg), K(tz_hour), K(tz_minuts));
|
|
}
|
|
}
|
|
|
|
// charset和collation相关
|
|
int64_t default_coll_int = static_cast<int64_t>(ObCharset::get_default_collation(
|
|
ObCharset::get_default_charset()));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (FALSE_IT(pos = 0)) {
|
|
} else if (OB_FAIL(databuff_printf(ObSpecialSysVarValues::default_coll_int_str_,
|
|
ObSpecialSysVarValues::COLL_INT_STR_MAX_LEN,
|
|
pos,
|
|
"%ld",
|
|
default_coll_int))) {
|
|
LOG_ERROR("fail to print coll to buff", K(ret), K(default_coll_int));
|
|
}
|
|
|
|
//OB_SV_SERVER_UUID
|
|
if (OB_SUCC(ret)) {
|
|
MEMSET(server_uuid_, '\0', SERVER_UUID_MAX_LEN);
|
|
if (OB_FAIL(ObExprUuid::gen_server_uuid(server_uuid_, SERVER_UUID_MAX_LEN - 1))) {
|
|
LOG_WARN("failed to gen server uuid", K(ret));
|
|
} else {/*do nothing*/}
|
|
}
|
|
}
|
|
|
|
static ObSpecialSysVarValues ob_special_sys_var_values_init;
|
|
|
|
const char *ObBoolSysVar::BOOL_TYPE_NAMES[] = {"OFF", "ON", 0};
|
|
|
|
const char *ObSqlModeVar::SQL_MODE_NAMES[] = {
|
|
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", ",",
|
|
"ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", "NO_DIR_IN_CREATE",
|
|
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
|
|
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
|
|
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
|
|
"STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE",
|
|
"ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL",
|
|
"NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION",
|
|
"PAD_CHAR_TO_FULL_LENGTH", "ERROR_ON_RESOLVE_CAST", "TIME_TRUNCATE_FRACTIONAL", 0};
|
|
|
|
const char * ObBasicSysVar::EMPTY_STRING = "";
|
|
|
|
int ObBasicSysVar::init(const ObObj &value,
|
|
const ObObj &min_val,
|
|
const ObObj &max_val,
|
|
ObObjType type,
|
|
int64_t flags)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_nullable = ((flags & ObSysVarFlag::NULLABLE) && (value.get_type() == ObNullType));
|
|
if (OB_UNLIKELY(!(value.get_type() == type || is_nullable))) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_ERROR("value type is unexpected", K(ret), K(value.get_type()), K(type), K(value));
|
|
} else if (!is_base_value_empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("base value should be empty", K(ret), K(value), K(base_value_));
|
|
} else {
|
|
base_value_ = value;
|
|
min_val_ = min_val;
|
|
max_val_ = max_val;
|
|
type_ = type;
|
|
flags_ = flags;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObBasicSysVar::reset()
|
|
{
|
|
base_version_ = OB_INVALID_VERSION;
|
|
clean_value();
|
|
type_ = ObUnknownType;
|
|
flags_ = ObSysVarFlag::NONE;
|
|
on_check_and_convert_ = NULL;
|
|
on_update_ = NULL;
|
|
to_select_obj_ = NULL;
|
|
to_show_str_ = NULL;
|
|
get_meta_type_ = NULL;
|
|
}
|
|
|
|
void ObBasicSysVar::clean_value()
|
|
{
|
|
clean_base_value();
|
|
clean_inc_value();
|
|
min_val_.reset();
|
|
max_val_.reset();
|
|
}
|
|
|
|
void ObBasicSysVar::clean_base_value()
|
|
{
|
|
base_version_ = OB_INVALID_VERSION;
|
|
base_value_.set_nop_value();
|
|
}
|
|
|
|
void ObBasicSysVar::clean_inc_value()
|
|
{
|
|
inc_value_.set_nop_value();
|
|
}
|
|
|
|
bool ObBasicSysVar::is_base_value_empty() const
|
|
{
|
|
return base_value_.is_nop_value();
|
|
}
|
|
|
|
bool ObBasicSysVar::is_inc_value_empty() const
|
|
{
|
|
return inc_value_.is_nop_value();
|
|
}
|
|
|
|
const ObString ObBasicSysVar::get_name() const
|
|
{
|
|
return ObSysVarFactory::get_sys_var_name_by_id(get_type());
|
|
}
|
|
|
|
/*
|
|
int ObBasicSysVar::is_need_serialize(bool &need_serialize) const
|
|
{
|
|
// hard code,不使用内部表__all_sys_variable保存的值
|
|
int ret = OB_SUCCESS;
|
|
int64_t sys_var_idx = -1;
|
|
if (OB_FAIL(ObSysVarFactory::calc_sys_var_store_idx(get_type(), sys_var_idx))) {
|
|
LOG_WARN("fail to calc sys var store idx", K(ret), K(sys_var_idx));
|
|
} else if (OB_UNLIKELY(sys_var_idx < 0) ||
|
|
OB_UNLIKELY(sys_var_idx >= ObSysVariables::get_all_sys_var_count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid sys var idx", K(ret),
|
|
K(sys_var_idx), K(ObSysVariables::get_all_sys_var_count()));
|
|
} else {
|
|
need_serialize = (0 != (ObSysVariables::get_flags(sys_var_idx) & ObSysVarFlag::NEED_SERIALIZE));
|
|
}
|
|
return ret;
|
|
}
|
|
*/
|
|
|
|
int ObBasicSysVar::log_err_wrong_value_for_var(int error_no, const ObObj &val) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
SMART_VAR(char[OB_MAX_SQL_LENGTH], val_str_buf) {
|
|
int64_t pos = 0;
|
|
if (OB_UNLIKELY(OB_ERR_WRONG_VALUE_FOR_VAR != error_no)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("error no must be OB_ERR_WRONG_VALUE_FOR_VAR",
|
|
K(ret), K(error_no), LITERAL_K(OB_ERR_WRONG_VALUE_FOR_VAR), K(lbt()));
|
|
} else if (OB_FAIL(val.print_plain_str_literal(val_str_buf, OB_MAX_SQL_LENGTH, pos))) {
|
|
LOG_WARN("fail to print_plain_str_literal", K(ret), K(OB_MAX_SQL_LENGTH), K(pos), K(lbt()));
|
|
} else {
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
|
|
get_name().length(), get_name().ptr(), static_cast<int>(pos), val_str_buf);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObObj cur_val = in_val;
|
|
if (OB_FAIL(do_check_and_convert(ctx, set_var, cur_val, out_val))) {
|
|
LOG_WARN("fail to do check", K(ret), K(in_val), K(cur_val));
|
|
} else if (FALSE_IT(cur_val = out_val)) {
|
|
} else if (NULL != on_check_and_convert_ &&
|
|
(OB_FAIL(on_check_and_convert_(ctx, set_var, *this, cur_val, out_val)))) {
|
|
LOG_WARN("fail to run on check", K(ret), K(in_val), K(cur_val));
|
|
} else {}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
UNUSED(set_var);
|
|
UNUSED(val);
|
|
return OB_SUCCESS;
|
|
}
|
|
|
|
int ObBasicSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
if (is_oracle_mode() && (ObNumberType == in_val.get_type())) {
|
|
number::ObNumber num = in_val.get_number();
|
|
int64_t int_val = 0;
|
|
if (num.is_valid_int64(int_val)) {
|
|
out_val.set_int(int_val);
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("not valid int value for var on oracle mode", K(in_val));
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::session_update(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString extra_var_name;
|
|
ObString extra_val;
|
|
ObCollationType extra_coll_type = CS_TYPE_INVALID;
|
|
bool should_update_extra_var = false;
|
|
ObObj extra_val_obj;
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("session is NULL", K(ret));
|
|
}
|
|
// 这里暂时写得有点乱,等下个版本就charset和collation不存两份了,只存collation,直接干掉这些代码
|
|
// 改变collation相关的系统变量的时候要同时改变对应的charset系统变量
|
|
if (OB_FAIL(ret)) {
|
|
} else if (set_var.var_name_ == OB_SV_COLLATION_SERVER ||
|
|
set_var.var_name_ == OB_SV_COLLATION_DATABASE ||
|
|
set_var.var_name_ == OB_SV_COLLATION_CONNECTION) {
|
|
ObString coll_str;
|
|
if (ObVarcharType == val.get_type()) {
|
|
coll_str = val.get_varchar();
|
|
} else if (ObIntType == val.get_type()) {
|
|
int64_t coll_int64 = val.get_int();
|
|
if (OB_UNLIKELY(false == ObCharset::is_valid_collation(coll_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid collation", K(ret), K(coll_int64), K(val));
|
|
} else {
|
|
const char *coll_str_ptr = ObCharset::collation_name(
|
|
static_cast<ObCollationType>(coll_int64));
|
|
coll_str = ObString(coll_str_ptr);
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid collation", K(ret), K(val));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(get_charset_var_and_val_by_collation(
|
|
set_var.var_name_, coll_str, extra_var_name, extra_val, extra_coll_type))) {
|
|
LOG_ERROR("fail to get charset variable and value by collation",
|
|
K(ret), K(set_var.var_name_), K(val), K(coll_str));
|
|
} else {
|
|
should_update_extra_var = true;
|
|
extra_val_obj.set_int(static_cast<int64_t>(extra_coll_type));
|
|
}
|
|
} else if (set_var.var_name_ == OB_SV_NLS_DATE_FORMAT
|
|
|| set_var.var_name_ == OB_SV_NLS_TIMESTAMP_FORMAT
|
|
|| set_var.var_name_ == OB_SV_NLS_TIMESTAMP_TZ_FORMAT) {
|
|
if (OB_UNLIKELY(val.is_null_oracle())) {
|
|
ret = OB_INVALID_DATE_FORMAT;
|
|
LOG_WARN("date format not recognized", K(ret), K(set_var.var_name_), K(val));
|
|
}
|
|
}
|
|
// 改变charset相关的系统变量的时候要同时改变对应的collation系统变量
|
|
else if (set_var.var_name_ == OB_SV_CHARACTER_SET_SERVER ||
|
|
set_var.var_name_ == OB_SV_CHARACTER_SET_DATABASE ||
|
|
set_var.var_name_ == OB_SV_CHARACTER_SET_CONNECTION) {
|
|
ObString cs_str;
|
|
if (ObVarcharType == val.get_type()) {
|
|
cs_str = val.get_varchar();
|
|
} else if (ObIntType == val.get_type()) {
|
|
int64_t coll_int64 = val.get_int();
|
|
if (OB_UNLIKELY(false == ObCharset::is_valid_collation(coll_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid charset", K(ret), K(coll_int64), K(val));
|
|
} else {
|
|
ObCharsetType cs_type = ObCharset::charset_type_by_coll(
|
|
static_cast<ObCollationType>(coll_int64));
|
|
if (OB_UNLIKELY(CHARSET_INVALID == cs_type)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("is valid collation, but has no valid charset", K(ret), K(coll_int64));
|
|
} else {
|
|
const char *cs_str_ptr = ObCharset::charset_name(cs_type);
|
|
cs_str = ObString(cs_str_ptr);
|
|
}
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid charset", K(ret), K(val));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(get_collation_var_and_val_by_charset(
|
|
set_var.var_name_, cs_str, extra_var_name, extra_val, extra_coll_type))) {
|
|
LOG_ERROR("fail to get collation variable and value by charset",
|
|
K(ret), K(set_var.var_name_), K(val), K(cs_str));
|
|
} else {
|
|
should_update_extra_var = true;
|
|
extra_val_obj.set_int(static_cast<int64_t>(extra_coll_type));
|
|
}
|
|
} else if (set_var.var_name_ == OB_SV__ENABLE_PARALLEL_QUERY) {
|
|
should_update_extra_var = true;
|
|
//
|
|
// 实现 Oracle 兼容行为方式如下:有变量 enable 和 parallel
|
|
// alter session enable parallel query 时 enable = true, parallel = 1 => 走 manual table dop 规则
|
|
// alter session disable parallel query 时 enable = false, parallel = 1 => 走 no parallel 规则
|
|
// alter session force parallel query parallel 1 时 enable = false, parallel = 1 => 走 no parallel 规则
|
|
// alter session force parallel query parallel 7 时 enable = true, parallel = 7 => 走 force parallel 规则
|
|
extra_var_name = ObString::make_string(OB_SV__FORCE_PARALLEL_QUERY_DOP);
|
|
extra_val_obj.set_uint64(1);
|
|
} else if (set_var.var_name_ == OB_SV__ENABLE_PARALLEL_DML) {
|
|
should_update_extra_var = true;
|
|
extra_var_name = ObString::make_string(OB_SV__FORCE_PARALLEL_DML_DOP);
|
|
extra_val_obj.set_uint64(1);
|
|
} else if (set_var.var_name_ == OB_SV__FORCE_PARALLEL_QUERY_DOP) {
|
|
should_update_extra_var = true;
|
|
uint64_t parallel = 0;
|
|
extra_var_name = ObString::make_string(OB_SV__ENABLE_PARALLEL_QUERY);
|
|
if (OB_FAIL(val.get_uint64(parallel))) {
|
|
LOG_WARN("unexpected parallel value type", K(val), K(ret));
|
|
} else if (1 == parallel) {
|
|
extra_val_obj.set_int(0);
|
|
} else {
|
|
extra_val_obj.set_int(1);
|
|
}
|
|
} else if (set_var.var_name_ == OB_SV__FORCE_PARALLEL_DDL_DOP) {
|
|
should_update_extra_var = true;
|
|
uint64_t parallel = 0;
|
|
extra_var_name = ObString::make_string(OB_SV__ENABLE_PARALLEL_DDL);
|
|
if (OB_FAIL(val.get_uint64(parallel))) {
|
|
LOG_WARN("unexpected parallel value type", K(val), K(ret));
|
|
} else if (1 == parallel) {
|
|
extra_val_obj.set_int(0);
|
|
} else {
|
|
extra_val_obj.set_int(1);
|
|
}
|
|
} else if (set_var.var_name_ == OB_SV__ENABLE_PARALLEL_DDL) {
|
|
should_update_extra_var = true;
|
|
extra_var_name = ObString::make_string(OB_SV__FORCE_PARALLEL_DDL_DOP);
|
|
extra_val_obj.set_uint64(1);
|
|
}
|
|
|
|
// 更新需要额外更新的系统变量
|
|
//FIXME 暂不考虑原子性
|
|
if (true == should_update_extra_var && OB_SUCC(ret)) {
|
|
if (OB_FAIL(session->update_sys_variable_by_name(extra_var_name, extra_val_obj))) {
|
|
LOG_ERROR("fail to set extra variable to session",
|
|
K(ret), K(extra_var_name), K(extra_val_obj));
|
|
} else {}
|
|
} else {}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(session->update_sys_variable_by_name(set_var.var_name_, val))) {
|
|
if (OB_LIKELY(OB_ERR_SYS_VARIABLE_UNKNOWN == ret)) {
|
|
LOG_USER_ERROR(OB_ERR_SYS_VARIABLE_UNKNOWN, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else {
|
|
LOG_WARN("fail to set variable to session", K(ret), K(set_var.var_name_), K(val));
|
|
}
|
|
} else {}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::update(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL != on_update_) {
|
|
if (OB_FAIL(on_update_(ctx, set_var, *this, val))) {
|
|
LOG_WARN("fail to on update", K(ret), K(set_var), K(val), K(*this));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObObjType ObBasicSysVar::inner_get_meta_type() const
|
|
{
|
|
return type_;
|
|
}
|
|
|
|
int ObBasicSysVar::inner_to_select_obj(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObObj &select_obj) const
|
|
{
|
|
UNUSED(allocator);
|
|
UNUSED(session);
|
|
int ret = OB_SUCCESS;
|
|
select_obj = get_value();
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::inner_to_show_str(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObString &show_str) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObObj &value = get_value();
|
|
const ObObj *res_obj = NULL;
|
|
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(&session);
|
|
ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, ObCharset::get_system_collation());
|
|
EXPR_CAST_OBJ_V2(ObVarcharType, value, res_obj);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(res_obj)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var casted obj ptr is NULL", K(ret), K(value), K(get_name()));
|
|
} else if (OB_UNLIKELY(ObVarcharType != res_obj->get_type())) {
|
|
LOG_WARN("sys var casted obj is not ObVarcharType",
|
|
K(ret), K(value), K(*res_obj), K(get_name()));
|
|
} else {
|
|
show_str = res_obj->get_varchar();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObBasicSysVar::get_base_version() const
|
|
{
|
|
return base_version_;
|
|
}
|
|
|
|
ObObjType ObBasicSysVar::get_meta_type() const
|
|
{
|
|
ObObjType ret_type = ObMaxType;
|
|
if (NULL == get_meta_type_) {
|
|
ret_type = inner_get_meta_type();
|
|
} else {
|
|
ret_type = get_meta_type_();
|
|
}
|
|
return ret_type;
|
|
}
|
|
|
|
const ObObj &ObBasicSysVar::get_value() const
|
|
{
|
|
return is_inc_value_empty() ? base_value_ : inc_value_;
|
|
}
|
|
|
|
const ObObj &ObBasicSysVar::get_base_value() const
|
|
{
|
|
return base_value_;
|
|
}
|
|
|
|
const ObObj &ObBasicSysVar::get_inc_value() const
|
|
{
|
|
return inc_value_;
|
|
}
|
|
|
|
const ObObj &ObBasicSysVar::get_min_val() const
|
|
{
|
|
return min_val_;
|
|
}
|
|
|
|
const ObObj &ObBasicSysVar::get_max_val() const
|
|
{
|
|
return max_val_;
|
|
}
|
|
|
|
void ObBasicSysVar::set_value(const ObObj &value)
|
|
{
|
|
inc_value_ = value;
|
|
}
|
|
|
|
ObObjType ObBasicSysVar::get_data_type() const
|
|
{
|
|
return type_;
|
|
}
|
|
|
|
void ObBasicSysVar::set_data_type(ObObjType type)
|
|
{
|
|
type_ = type;
|
|
}
|
|
|
|
void ObBasicSysVar::set_flags(int64_t flags)
|
|
{
|
|
flags_ = flags;
|
|
}
|
|
|
|
int ObBasicSysVar::to_select_obj(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObObj &select_obj) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == to_select_obj_) {
|
|
if (OB_FAIL(inner_to_select_obj(allocator, session, select_obj))) {
|
|
LOG_WARN("fail to call inner_to_select_obj", K(ret), K(*this));
|
|
} else {}
|
|
} else {
|
|
if (OB_FAIL(to_select_obj_(allocator, session, *this, select_obj))) {
|
|
LOG_WARN("fail to call to_select_obj_", K(ret), K(*this));
|
|
} else {}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::to_show_str(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObString &show_str) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == to_show_str_) {
|
|
if (OB_FAIL(inner_to_show_str(allocator, session, show_str))) {
|
|
LOG_WARN("fail to call inner_to_show_str", K(ret), K(*this));
|
|
} else {}
|
|
} else {
|
|
if (OB_FAIL(to_show_str_(allocator, session, *this, show_str))) {
|
|
LOG_WARN("fail to call to_show_str_", K(ret), K(*this));
|
|
} else {}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int ObBasicSysVar::get_charset_var_and_val_by_collation(const ObString &coll_var_name,
|
|
const ObString &coll_val,
|
|
ObString &cs_var_name,
|
|
ObString &cs_val,
|
|
ObCollationType &coll_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ObCharsetSysVarPair::get_charset_var_by_collation_var(
|
|
coll_var_name, cs_var_name))) {
|
|
LOG_ERROR("fail to get collation variable by charset variable",
|
|
K(ret), K(coll_var_name));
|
|
} else if (OB_FAIL(ObCharset::charset_name_by_coll(coll_val, cs_val))) {
|
|
LOG_ERROR("fail to get charset type by collation", K(ret), K(coll_val));
|
|
} else {
|
|
coll_type = ObCharset::collation_type(coll_val);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::get_collation_var_and_val_by_charset(const ObString &cs_var_name,
|
|
const ObString &cs_val,
|
|
ObString &coll_var_name,
|
|
ObString &coll_val,
|
|
ObCollationType &coll_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ObCharsetSysVarPair::get_collation_var_by_charset_var(
|
|
cs_var_name, coll_var_name))) {
|
|
LOG_ERROR("fail to get charset variable by collation variable", K(ret), K(cs_var_name));
|
|
} else {
|
|
coll_type = CS_TYPE_INVALID;
|
|
ObCharsetType cs_type = ObCharset::charset_type(cs_val);
|
|
if (OB_UNLIKELY(CHARSET_INVALID == cs_type)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid charset type", K(ret), K(cs_val));
|
|
} else if (OB_FAIL(ObCharset::get_default_collation(cs_type, coll_type))) {
|
|
LOG_ERROR("fail to get default collation", K(ret), K(cs_type));
|
|
} else if (OB_FAIL(ObCharset::collation_name(coll_type, coll_val))) {
|
|
LOG_ERROR("fail to get collation name", K(ret), K(coll_type));
|
|
} else {
|
|
// empty
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::check_and_convert_int_tc_value(const common::ObObj &value,
|
|
int64_t invalid_value,
|
|
int64_t &result_value) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t int_value = 0;
|
|
switch (value.get_type()) {
|
|
case ObTinyIntType:
|
|
int_value = value.get_tinyint();
|
|
break;
|
|
case ObSmallIntType:
|
|
int_value = value.get_smallint();
|
|
break;
|
|
case ObMediumIntType:
|
|
int_value = value.get_mediumint();
|
|
break;
|
|
case ObInt32Type:
|
|
int_value = value.get_int32();
|
|
break;
|
|
case ObIntType:
|
|
int_value = value.get_int();
|
|
break;
|
|
default:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("unexpected type", K(ret), K(value.get_type()));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (int_value < 0 || int_value >= invalid_value) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
} else {
|
|
result_value = int_value;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObBasicSysVar::check_and_convert_uint_tc_value(const common::ObObj &value,
|
|
uint64_t invalid_value,
|
|
uint64_t &result_value) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t uint_value = 0;
|
|
switch (value.get_type()) {
|
|
case ObUTinyIntType:
|
|
uint_value = value.get_utinyint();
|
|
break;
|
|
case ObUSmallIntType:
|
|
uint_value = value.get_usmallint();
|
|
break;
|
|
case ObUMediumIntType:
|
|
uint_value = value.get_umediumint();
|
|
break;
|
|
case ObUInt32Type:
|
|
uint_value = value.get_uint32();
|
|
break;
|
|
case ObUInt64Type:
|
|
uint_value = value.get_uint64();
|
|
break;
|
|
default:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("unexpected type", K(ret), K(value.get_type()));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (uint_value >= invalid_value) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
} else {
|
|
result_value = uint_value;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
DEF_TO_STRING(ObBasicSysVar)
|
|
{
|
|
int64_t pos = 0;
|
|
J_OBJ_START();
|
|
J_KV("sys_var_name", get_name(), "sys_var_id", get_type(),
|
|
K_(base_value), K_(inc_value), K_(type), K_(flags), K_(is_enum_type));
|
|
J_OBJ_END();
|
|
return pos;
|
|
}
|
|
|
|
// base_value只是存储基线数据,目前看需要序列化的场景一定是操作增量数据。
|
|
//OB_SERIALIZE_MEMBER(ObBasicSysVar, inc_value_, type_, flags_);
|
|
|
|
OB_DEF_SERIALIZE(ObBasicSysVar)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LST_DO_CODE(OB_UNIS_ENCODE, get_value(), type_, flags_, is_enum_type_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObBasicSysVar)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LST_DO_CODE(OB_UNIS_DECODE, inc_value_, type_, flags_, is_enum_type_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObBasicSysVar)
|
|
{
|
|
int64_t len = 0;
|
|
LST_DO_CODE(OB_UNIS_ADD_LEN, get_value(), type_, flags_, is_enum_type_);
|
|
return len;
|
|
}
|
|
|
|
void ObTypeLibSysVar::reset()
|
|
{
|
|
ObBasicSysVar::reset();
|
|
type_lib_.reset();
|
|
}
|
|
|
|
int ObTypeLibSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// 为了跟mysql表现得一样,这里不判断flags_中是否带有ObSysVarFlag::NULLABLE,
|
|
// 而在do_check_and_convert函数中判断in_val的type为ObNullType再报错
|
|
if (true == set_var.is_set_default_ || ObNullType == val.get_type()) {
|
|
// do nothing
|
|
} else if (false == ob_is_integer_type(val.get_type())
|
|
&& false == ob_is_string_type(val.get_type())) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
if (is_oracle_mode()) {
|
|
if (ObNumberType == val.get_type()) {
|
|
number::ObNumber num = val.get_number();
|
|
if (num.is_valid_int()) {
|
|
ret = OB_SUCCESS;
|
|
LOG_DEBUG("number is valid int", K(val), K(num));
|
|
}
|
|
} else if (ob_is_decimal_int(val.get_type())) {
|
|
int tmp_ret = ret;
|
|
bool is_valid_int64 = false;
|
|
int64_t res_v = 0;
|
|
if (OB_FAIL(wide::check_range_valid_int64(val.get_decimal_int(), val.get_int_bytes(),
|
|
is_valid_int64, res_v))) {
|
|
LOG_WARN("check valid int64 failed", K(ret));
|
|
} else if (is_valid_int64) {
|
|
ret = OB_SUCCESS;
|
|
LOG_DEBUG("decimal int is valid int", K(val), K(res_v));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCCESS != ret) {
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
} else {}
|
|
return ret;
|
|
}
|
|
|
|
int ObTypeLibSysVar::inner_to_show_str(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObString &show_str) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObObj &value = get_value();
|
|
if (OB_UNLIKELY(false == ob_is_integer_type(value.get_type()))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid type of type lib", K(*this), K(value.get_type()));
|
|
} else {
|
|
const ObObj *res_obj = NULL;
|
|
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(&session);
|
|
ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, ObCharset::get_system_collation());
|
|
EXPR_CAST_OBJ_V2(ObUInt64Type, value, res_obj);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(res_obj)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var casted obj ptr is NULL", K(ret), K(value), K(get_name()));
|
|
} else if (OB_UNLIKELY(ObUInt64Type != res_obj->get_type())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var casted obj is not ObUInt64Type", K(ret),
|
|
K(value), K(*res_obj), K(get_name()));
|
|
} else {
|
|
int64_t type_lib_idx = static_cast<int64_t>(res_obj->get_uint64()); // FIXME 这里不考虑溢出
|
|
if (OB_UNLIKELY(type_lib_idx < 0) || OB_UNLIKELY(type_lib_idx >= type_lib_.count_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid type lib idx", K(ret), K(type_lib_idx), K(value), K(get_name()));
|
|
} else {
|
|
show_str = ObString(type_lib_.type_names_[type_lib_idx]);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTypeLibSysVar::find_type(const ObString &type, int64_t &type_index) const
|
|
{
|
|
int ret = OB_ENTRY_NOT_EXIST;
|
|
for (int64_t i = 0; OB_ENTRY_NOT_EXIST == ret && i < type_lib_.count_; ++i) {
|
|
if (0 == type.case_compare(type_lib_.type_names_[i])) {
|
|
type_index = i;
|
|
ret = OB_SUCCESS;
|
|
} else {}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTypeLibSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (ObNullType == in_val.get_type()) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, set_var.var_name_.length(),
|
|
set_var.var_name_.ptr(), (int)strlen("NULL"), "NULL");
|
|
} else if (true == ob_is_string_type(in_val.get_type())) {
|
|
ObString str_val;
|
|
int64_t type_idx = -1;
|
|
if (ObCharType == in_val.get_type() || ObVarcharType == in_val.get_type()) {
|
|
if (OB_FAIL(in_val.get_string(str_val))) {
|
|
LOG_ERROR("fail to get char", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("unexpected type", K(ret), K(in_val));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(find_type(str_val, type_idx))) {
|
|
if (OB_LIKELY(OB_ENTRY_NOT_EXIST == ret)) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else {
|
|
LOG_WARN("fail to find type", K(ret), K(str_val), K(in_val));
|
|
}
|
|
} else if (OB_UNLIKELY(type_idx < 0) || OB_UNLIKELY(type_idx >= type_lib_.count_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("type idx is invalid", K(ret), K(type_idx), K(str_val), K(in_val));
|
|
} else {
|
|
out_val.set_int(type_idx);
|
|
}
|
|
} else if (true == ob_is_int_tc(in_val.get_type())) {
|
|
int64_t int64_val = 0;
|
|
if (OB_FAIL(check_and_convert_int_tc_value(in_val, type_lib_.count_, int64_val))) {
|
|
if (OB_LIKELY(OB_ERR_WRONG_VALUE_FOR_VAR == ret)) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else {
|
|
LOG_WARN("fail to check int tc value", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
out_val.set_int(int64_val);
|
|
}
|
|
} else if (true == ob_is_uint_tc(in_val.get_type())) {
|
|
uint64_t uint64_val = 0;
|
|
if (OB_FAIL(check_and_convert_uint_tc_value(in_val, type_lib_.count_, uint64_val))) {
|
|
if (OB_LIKELY(OB_ERR_WRONG_VALUE_FOR_VAR == ret)) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else {
|
|
LOG_WARN("fail to check uint tc value", K(ret), K(in_val));
|
|
}
|
|
} else if (uint64_val > static_cast<uint64_t>(INT64_MAX)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("value is lager than INT64_MAX", K(ret), K(uint64_val), K(in_val));
|
|
} else {
|
|
out_val.set_int(static_cast<int64_t>(uint64_val));
|
|
}
|
|
} else if (is_oracle_mode() && (ObNumberType == in_val.get_type())) {
|
|
number::ObNumber num = in_val.get_number();
|
|
int64_t int_val = 0;
|
|
if (num.is_valid_int64(int_val)) {
|
|
if (int_val < 0 || int_val >= type_lib_.count_) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else {
|
|
out_val.set_int(int_val);
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("not valid int value for var on oracle mode", K(in_val));
|
|
}
|
|
} else if (is_oracle_mode() && ob_is_decimal_int(in_val.get_type())) {
|
|
int64_t res_v = 0;
|
|
bool is_valid_int64 = false;
|
|
if (OB_FAIL(wide::check_range_valid_int64(in_val.get_decimal_int(), in_val.get_int_bytes(),
|
|
is_valid_int64, res_v))) {
|
|
LOG_WARN("check int64 range failed", K(ret));
|
|
} else if (is_valid_int64) {
|
|
if (res_v < 0 || res_v >= type_lib_.count_) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else {
|
|
out_val.set_int(res_v);
|
|
}
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid type", K(ret), K(in_val.get_type()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObEnumSysVar::inner_to_select_obj(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
ObObj &select_obj) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString show_str;
|
|
if (OB_FAIL(inner_to_show_str(allocator, session, show_str))) {
|
|
LOG_WARN("fail to convert to show str", K(ret), K(get_value()));
|
|
} else {
|
|
// 对于ObEnumSysVar类,inner_to_select_obj和inner_to_show_str显示的内容一样
|
|
select_obj.set_varchar(show_str);
|
|
select_obj.set_collation_type(ObCharset::get_system_collation());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObCharsetSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (false == ob_is_integer_type(val.get_type())
|
|
&& false == ob_is_string_type(val.get_type())) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
if (is_oracle_mode() && ObNumberType == val.get_type()) {
|
|
number::ObNumber num = val.get_number();
|
|
if (num.is_valid_int()) {
|
|
ret = OB_SUCCESS;
|
|
LOG_DEBUG("number is valid int", K(val), K(num));
|
|
}
|
|
}
|
|
if (OB_SUCCESS != ret) {
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObCharsetSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("session is NULL", K(ret), K(*this));
|
|
} else if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (ObNullType == in_val.get_type()) {
|
|
if (0 != (flags_ & ObSysVarFlag::NULLABLE)) {
|
|
// do nothing
|
|
} else {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, set_var.var_name_.length(),
|
|
set_var.var_name_.ptr(), (int)strlen("NULL"), "NULL");
|
|
}
|
|
} else if (true == ob_is_string_type(in_val.get_type())) {
|
|
ObCastCtx cast_ctx(&ctx.get_allocator(), &dtc_params, CM_NONE, ObCharset::get_system_collation());
|
|
ObObj buf_obj;
|
|
const ObObj *res_obj_ptr = NULL;
|
|
if (OB_FAIL(ObObjCaster::to_type(ObVarcharType, cast_ctx, in_val, buf_obj, res_obj_ptr))) {
|
|
LOG_WARN("failed to cast object to ObVarcharType ", K(ret), K(in_val));
|
|
} else if (OB_ISNULL(res_obj_ptr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("succ to cast obj, but res_obj_ptr is NULL", K(ret));
|
|
} else {
|
|
out_val = *res_obj_ptr;
|
|
}
|
|
} else if (true == ob_is_integer_type(in_val.get_type())) {
|
|
ObCastCtx cast_ctx(&ctx.get_allocator(), &dtc_params, CM_NONE, ObCharset::get_system_collation());
|
|
ObObj buf_obj;
|
|
const ObObj *res_obj_ptr = NULL;
|
|
if (OB_FAIL(ObObjCaster::to_type(ObIntType, cast_ctx, in_val, buf_obj, res_obj_ptr))) {
|
|
LOG_WARN("failed to cast object to ObIntType ", K(ret), K(in_val));
|
|
} else if (OB_ISNULL(res_obj_ptr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("succ to cast obj, but res_obj_ptr is NULL", K(ret));
|
|
} else {
|
|
out_val = *res_obj_ptr;
|
|
}
|
|
} else if (is_oracle_mode() && (ObNumberType == in_val.get_type())) {
|
|
number::ObNumber num = in_val.get_number();
|
|
int64_t int_val = 0;
|
|
if (num.is_valid_int64(int_val)) {
|
|
out_val.set_int(int_val);
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("not valid int value for var on oracle mode", K(in_val));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("invalid type ", K(ret), K(in_val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTinyintSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (ObTinyIntType != val.get_type()) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
if (is_oracle_mode() && ObNumberType == val.get_type()) {
|
|
number::ObNumber num = val.get_number();
|
|
//do value range check in do_check_and_convert
|
|
if (num.is_valid_int()) {
|
|
ret = OB_SUCCESS;
|
|
LOG_DEBUG("number is valid int", K(val), K(num));
|
|
} else {
|
|
LOG_WARN("number is not valid int for sys var on oracle mode", K(val), K(num));
|
|
}
|
|
}
|
|
if (OB_SUCCESS != ret) {
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTinyintSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (is_oracle_mode() && (ObNumberType == in_val.get_type())) {
|
|
number::ObNumber num = in_val.get_number();
|
|
int64_t int_val = 0;
|
|
if (num.is_valid_int64(int_val)) {
|
|
ObObj tmp_val;
|
|
tmp_val.set_int(int_val);
|
|
if (OB_FAIL(check_and_convert_int_tc_value(tmp_val, (1LL << 8), int_val))) {
|
|
if (OB_ERR_WRONG_VALUE_FOR_VAR == ret) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
} else {}
|
|
} else {
|
|
LOG_WARN("fail to check uint tc value", K(ret), K(in_val));
|
|
}
|
|
LOG_WARN("value is not valid tinyint for sys var on oracle mode", K(in_val), K(out_val));
|
|
} else {
|
|
out_val.set_tinyint(static_cast<int8_t>(int_val));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("not valid int value for sys var on oracle mode", K(in_val));
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIntSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (false == ob_is_integer_type(val.get_type())
|
|
&& ObNumberType != val.get_type()
|
|
&& ObDecimalIntType != val.get_type()) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIntSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_converted = false;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (OB_FAIL(do_convert(ctx, in_val, out_val, is_converted))) {
|
|
LOG_WARN("fail to convert variable", K(ret), K(set_var.var_name_));
|
|
} else if (is_converted && OB_FAIL(ObSysVarUtils::log_bounds_error_or_warning(
|
|
ctx, set_var, in_val))) {
|
|
if (OB_UNLIKELY(OB_ERR_WRONG_VALUE_FOR_VAR != ret)) {
|
|
LOG_WARN("fail to log bounds error or warnning", K(ret));
|
|
} else {
|
|
LOG_WARN("wrong value for sys var", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define CHECK_DECIMAL_INT_VALID(TYPE) \
|
|
case sizeof(TYPE##_t): { \
|
|
const TYPE##_t &l = *(decint->TYPE##_v_); \
|
|
const TYPE##_t r = get_scale_factor<TYPE##_t>(scale); \
|
|
is_in_val_valid = ((l % r) == 0); \
|
|
if (is_in_val_valid) { \
|
|
div_res_val.from(l / r); \
|
|
} \
|
|
break; \
|
|
}
|
|
|
|
int ObIntSysVar::do_convert(ObExecContext &ctx,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val,
|
|
bool &is_converted)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_converted = false;
|
|
ObExprCtx expr_ctx;
|
|
ObObj tmp_obj;
|
|
if (OB_UNLIKELY(ObIntType != type_ && ObUInt64Type != type_) ||
|
|
OB_ISNULL(expr_ctx.phy_plan_ctx_ = ctx.get_physical_plan_ctx()) ||
|
|
OB_ISNULL(expr_ctx.my_session_ = ctx.get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("type_ is neigher ObIntType nor ObUInt64Type, "
|
|
"or physical plan ctx in ObExecContext is not NULL, "
|
|
"or session in ObExecContext is NULL", K(ret),
|
|
K(type_), K(expr_ctx.phy_plan_ctx_), K(expr_ctx.my_session_));
|
|
} else {
|
|
expr_ctx.calc_buf_ = &(ctx.get_allocator());
|
|
expr_ctx.exec_ctx_ = &ctx;
|
|
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_WARN_ON_FAIL);
|
|
|
|
// FIXME(yyy),因为当前ob在parser阶段将所有大于int32的数值均转换为decimal处理,与mysql不兼容;
|
|
// 因此,在这里进行特殊处理
|
|
if (OB_FAIL(ret)) {
|
|
} else if (ObNumberType == in_val.get_type()) {
|
|
common::number::ObNumber in_number;
|
|
int64_t int_val = 0;
|
|
uint64_t uint_val = 0;
|
|
if (OB_FAIL(in_val.get_number(in_number))) {
|
|
LOG_WARN("fail to get number", K(ret), K(in_val));
|
|
} else if (in_number.is_valid_int64(int_val)) {
|
|
tmp_obj.set_int(int_val);
|
|
} else if (in_number.is_valid_uint64(uint_val)) {
|
|
tmp_obj.set_uint64(uint_val);
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for int variables", K(ret), K(in_val));
|
|
}
|
|
} else if (ObDecimalIntType == in_val.get_type()) {
|
|
bool is_in_val_valid = false;
|
|
const ObDecimalInt *decint = in_val.get_decimal_int();
|
|
const int32_t int_bytes = in_val.get_int_bytes();
|
|
const int16_t scale = in_val.get_scale();
|
|
ObDecimalIntBuilder div_res_val;
|
|
switch (int_bytes) {
|
|
CHECK_DECIMAL_INT_VALID(int32)
|
|
CHECK_DECIMAL_INT_VALID(int64)
|
|
CHECK_DECIMAL_INT_VALID(int128)
|
|
CHECK_DECIMAL_INT_VALID(int256)
|
|
CHECK_DECIMAL_INT_VALID(int512)
|
|
default: {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("int_bytes is unexpected", K(ret), K(int_bytes));
|
|
break;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (is_in_val_valid) {
|
|
int64_t tmp_int = 0;
|
|
uint64_t tmp_uint = 0;
|
|
if (OB_FAIL(wide::check_range_valid_int64(div_res_val.get_decimal_int(),
|
|
div_res_val.get_int_bytes(), is_in_val_valid, tmp_int))) {
|
|
LOG_WARN("check_range_valid_int64 failed", K(ret), K(div_res_val.get_int_bytes()));
|
|
} else if (is_in_val_valid) {
|
|
tmp_obj.set_int(tmp_int);
|
|
} else if (OB_FAIL(wide::check_range_valid_uint64(div_res_val.get_decimal_int(),
|
|
div_res_val.get_int_bytes(), is_in_val_valid, tmp_uint))) {
|
|
LOG_WARN("check_range_valid_uint64 failed", K(ret), K(div_res_val.get_int_bytes()));
|
|
} else if (is_in_val_valid) {
|
|
tmp_obj.set_uint64(tmp_uint);
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for int variables", K(ret), K(in_val), K(int_bytes), K(scale));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for int variables", K(ret), K(in_val), K(int_bytes), K(scale));
|
|
}
|
|
}
|
|
} else {
|
|
tmp_obj = in_val;
|
|
}
|
|
|
|
// cast input_value to the variable's data_type
|
|
if (OB_FAIL(ret)) {
|
|
} else if ((ob_is_int_tc(type_) && ob_is_uint_tc(tmp_obj.get_type())) ||
|
|
(ob_is_uint_tc(type_) && ob_is_int_tc(tmp_obj.get_type()))) {
|
|
const ObObj *out_val_ptr = NULL;
|
|
EXPR_CAST_OBJ_V2(type_, tmp_obj, out_val_ptr);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(out_val_ptr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("succ to cast obj, but out_val_ptr is NULL", K(ret), K(type_), K(tmp_obj));
|
|
} else {
|
|
out_val = *out_val_ptr;
|
|
is_converted = out_val_ptr != &tmp_obj ? true : false;
|
|
//判断是否进行了值的转换(只是类型的转换不应该设置is_converted)
|
|
if (out_val_ptr != &tmp_obj) {
|
|
if (ObIntType == type_) {
|
|
is_converted = static_cast<uint64_t>(out_val_ptr->get_int()) != tmp_obj.get_uint64() ?
|
|
true : false;
|
|
} else {
|
|
is_converted = out_val_ptr->get_uint64() != static_cast<uint64_t>(tmp_obj.get_int()) ?
|
|
true : false;
|
|
}
|
|
} else {}
|
|
}
|
|
} else {
|
|
out_val = tmp_obj;
|
|
}
|
|
|
|
// adjust the out_val to meet variable's valid range
|
|
if (OB_SUCC(ret)) {
|
|
if (!min_val_.is_null() && out_val < min_val_) {
|
|
out_val = min_val_;
|
|
is_converted = true;
|
|
}
|
|
if (!max_val_.is_null() && out_val > max_val_) {
|
|
out_val = max_val_;
|
|
is_converted = true;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
#undef CHECK_DECIMAL_INT_VALID
|
|
|
|
int ObStrictRangeIntSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObExprCtx expr_ctx;
|
|
ObObj tmp_obj;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (OB_UNLIKELY(ObIntType != type_ && ObUInt64Type != type_) ||
|
|
OB_ISNULL(expr_ctx.phy_plan_ctx_ = ctx.get_physical_plan_ctx()) ||
|
|
OB_ISNULL(expr_ctx.my_session_ = ctx.get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("type_ is neigher ObIntType nor ObUInt64Type, "
|
|
"or physical plan ctx in ObExecContext is not NULL, "
|
|
"or session in ObExecContext is NULL", K(ret),
|
|
K(type_), K(expr_ctx.phy_plan_ctx_), K(expr_ctx.my_session_));
|
|
} else {
|
|
expr_ctx.calc_buf_ = &(ctx.get_allocator());
|
|
expr_ctx.exec_ctx_ = &ctx;
|
|
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_WARN_ON_FAIL);
|
|
|
|
// FIXME(yyy),因为当前ob在parser阶段将所有大于int32的数值均转换为decimal处理,与mysql不兼容;
|
|
// 因此,在这里进行特殊处理
|
|
if (OB_FAIL(ret)) {
|
|
} else if (ObNumberType == in_val.get_type()) {
|
|
common::number::ObNumber in_number;
|
|
int64_t int_val = 0;
|
|
uint64_t uint_val = 0;
|
|
if (OB_FAIL(in_val.get_number(in_number))) {
|
|
LOG_WARN("fail to get number", K(ret), K(in_val));
|
|
} else if (in_number.is_valid_int64(int_val)) {
|
|
tmp_obj.set_int(int_val);
|
|
} else if (in_number.is_valid_uint64(uint_val)) {
|
|
tmp_obj.set_uint64(uint_val);
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for int variables", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
tmp_obj = in_val;
|
|
}
|
|
|
|
// cast input_value to the variable's data_type
|
|
if (OB_FAIL(ret)) {
|
|
} else if ((ob_is_int_tc(type_) && ob_is_uint_tc(tmp_obj.get_type())) ||
|
|
(ob_is_uint_tc(type_) && ob_is_int_tc(tmp_obj.get_type()))) {
|
|
const ObObj *out_val_ptr = NULL;
|
|
EXPR_CAST_OBJ_V2(type_, tmp_obj, out_val_ptr);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(out_val_ptr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("succ to cast obj, but out_val_ptr is NULL", K(ret), K(type_), K(tmp_obj));
|
|
} else {
|
|
out_val = *out_val_ptr;
|
|
}
|
|
} else {
|
|
out_val = tmp_obj;
|
|
}
|
|
|
|
// check the out_val's range
|
|
if (OB_SUCC(ret)) {
|
|
if (!min_val_.is_null() && out_val < min_val_) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
} else if (!max_val_.is_null() && out_val > max_val_) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObNumericSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (false == ob_is_numeric_type(val.get_type())) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObNumericSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_converted = false;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (OB_FAIL(do_convert(ctx, in_val, out_val, is_converted))) {
|
|
LOG_WARN("fail to convert variable", K(ret), K(set_var.var_name_));
|
|
} else if (is_converted && OB_FAIL(ObSysVarUtils::log_bounds_error_or_warning(
|
|
ctx, set_var, in_val))) {
|
|
if (OB_UNLIKELY(OB_ERR_WRONG_VALUE_FOR_VAR != ret)) {
|
|
LOG_WARN("fail to log bounds error or warnning", K(ret));
|
|
} else {
|
|
LOG_WARN("wrong value for sys var", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObNumericSysVar::do_convert(ObExecContext &ctx,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val,
|
|
bool &is_converted)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_converted = false;
|
|
ObExprCtx expr_ctx;
|
|
expr_ctx.calc_buf_ = &(ctx.get_allocator());
|
|
expr_ctx.my_session_ = ctx.get_my_session();
|
|
expr_ctx.cast_mode_ = CM_NONE;
|
|
expr_ctx.phy_plan_ctx_ = ctx.get_physical_plan_ctx();
|
|
const ObObj *res_obj = NULL;
|
|
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
|
|
EXPR_CAST_OBJ_V2(ObNumberType, in_val, res_obj);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(res_obj)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("succ to cast obj, but res_obj is null", K(ret), K(in_val));
|
|
} else {
|
|
out_val = *res_obj;
|
|
|
|
// adjust the out_val to meet variable's valid range
|
|
if (!min_val_.is_null() && out_val < min_val_) {
|
|
out_val = min_val_;
|
|
is_converted = true;
|
|
}
|
|
if (!max_val_.is_null() && out_val > max_val_) {
|
|
out_val = max_val_;
|
|
is_converted = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVarcharSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (lib::is_oracle_mode() && ob_is_null(val.get_type())) {
|
|
//'' will be regard as NULL in oracle mode, let it go
|
|
} else if (false == ob_is_string_type(val.get_type())) {
|
|
if (set_var.var_name_ == OB_SV_NLS_DATE_FORMAT
|
|
|| set_var.var_name_ == OB_SV_NLS_TIMESTAMP_FORMAT
|
|
|| set_var.var_name_ == OB_SV_NLS_TIMESTAMP_TZ_FORMAT) {
|
|
ret = OB_INVALID_DATE_FORMAT;
|
|
LOG_WARN("date format not recognized", K(ret), K(set_var.var_name_), K(val));
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObVarcharSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
// TODO 像mysql那样做隐式转换
|
|
UNUSED(ctx);
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return OB_SUCCESS;
|
|
}
|
|
|
|
int ObTimeZoneSysVar::check_update_type(const ObSetVar &set_var, const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == val.get_type())) {
|
|
// do nothing
|
|
} else if (false == ob_is_string_type(val.get_type())) {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("wrong type for var", K(ret), K(val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTimeZoneSysVar::find_pos_time_zone(ObExecContext &ctx, const ObString &str_val, const bool is_oracle_compatible)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
ObCollationType coll_type = CS_TYPE_INVALID;;
|
|
ObTimeZoneInfoPos tz_info;
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid parameter", K(session), K(ret));
|
|
} else if (OB_FAIL(session->get_collation_connection(coll_type))) {
|
|
LOG_WARN("fail to get connection collation", K(coll_type), K(ret));
|
|
} else {
|
|
uint64_t tenant_id = session->get_effective_tenant_id();
|
|
int32_t no_sp_len = static_cast<int32_t>(ObCharset::strlen_byte_no_sp(coll_type,
|
|
str_val.ptr(),
|
|
str_val.length()));
|
|
ObString val_no_sp(no_sp_len, str_val.ptr());
|
|
if (is_oracle_compatible) {
|
|
val_no_sp = val_no_sp.trim();
|
|
}
|
|
ObTZMapWrap tz_map_wrap;
|
|
ObTimeZoneInfoManager *tz_info_mgr = NULL;
|
|
if (OB_FAIL(OTTZ_MGR.get_tenant_timezone(tenant_id, tz_map_wrap, tz_info_mgr))) {
|
|
LOG_WARN("get tenant timezone failed", K(ret));
|
|
} else if (OB_ISNULL(tz_info_mgr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("tz info mgr is null", K(ret));
|
|
} else if (OB_FAIL(tz_info_mgr->find_time_zone_info(val_no_sp, tz_info))) {
|
|
LOG_WARN("fail to find time zone", K(str_val), K(val_no_sp), K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTimeZoneSysVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_
|
|
|| (0 != (flags_ & ObSysVarFlag::NULLABLE) && ObNullType == in_val.get_type())) {
|
|
// do nothing
|
|
} else {
|
|
ObString str_val;
|
|
int32_t offset = 0;
|
|
|
|
if (ObCharType == in_val.get_type()) {
|
|
if (OB_FAIL(in_val.get_string(str_val))) {
|
|
LOG_ERROR("fail to get char", K(ret), K(in_val));
|
|
} else {}
|
|
} else if (ObVarcharType == in_val.get_type()) {
|
|
if (OB_FAIL(in_val.get_varchar(str_val))) {
|
|
LOG_ERROR("fail to get varchar", K(ret), K(in_val));
|
|
} else {}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("unexpected type", K(ret), K(in_val));
|
|
}
|
|
|
|
const bool is_oracle_compatible = (NULL != ctx.get_my_session() ? is_oracle_mode() : false);
|
|
CHECK_COMPATIBILITY_MODE(ctx.get_my_session());
|
|
int ret_more = OB_SUCCESS;
|
|
if (OB_SUCC(ret) && OB_FAIL(ObTimeConverter::str_to_offset(str_val, offset,
|
|
ret_more, is_oracle_compatible, true))) {
|
|
if (OB_ERR_UNKNOWN_TIME_ZONE != ret) {
|
|
LOG_WARN("fail to conver time zone", K(ret), K(str_val), K(is_oracle_compatible));
|
|
} else if (OB_FAIL(find_pos_time_zone(ctx, str_val, is_oracle_compatible))) {
|
|
LOG_WARN("fail to convert time zone", K(ret), K(ret_more), K(str_val));
|
|
if (OB_SUCCESS != ret_more && is_oracle_compatible) {
|
|
ret = ret_more;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
out_val = in_val;
|
|
} else if (OB_ERR_UNKNOWN_TIME_ZONE == ret) {
|
|
LOG_USER_ERROR(OB_ERR_UNKNOWN_TIME_ZONE, str_val.length(), str_val.ptr());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlModeVar::do_check_and_convert(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val, ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
ObSQLMode sql_mode = 0;
|
|
if (in_val.get_type() == ObNullType) {
|
|
sql_mode = 0;
|
|
} else if (true == ob_is_string_type(in_val.get_type())) {
|
|
ObString str_val;
|
|
if (ObCharType == in_val.get_type()) {
|
|
if (OB_FAIL(in_val.get_string(str_val))) {
|
|
LOG_ERROR("fail to get char", K(ret), K(in_val));
|
|
}
|
|
} else if (ObVarcharType == in_val.get_type()) {
|
|
if (OB_FAIL(in_val.get_varchar(str_val))) {
|
|
LOG_ERROR("fail to get varchar", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
}
|
|
}
|
|
ObString val_without_space = str_val.trim_space_only();
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(find_set(val_without_space))) {
|
|
LOG_WARN("fail to find type", K(ret), K(val_without_space), K(in_val));
|
|
} else if (OB_FAIL(ob_str_to_sql_mode(val_without_space, sql_mode))) {
|
|
LOG_WARN("fail to convert str to sql mode", K(ret), K(val_without_space), K(in_val));
|
|
}
|
|
} else if (ob_is_int_tc(in_val.get_type())) {
|
|
int64_t int64_val = 0;
|
|
if (OB_FAIL(check_and_convert_int_tc_value(in_val, (1LL << 32), int64_val))) {
|
|
if (OB_ERR_WRONG_VALUE_FOR_VAR == ret) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
} else {}
|
|
} else {
|
|
LOG_WARN("fail to check int tc value", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
sql_mode = static_cast<uint64_t>(int64_val);
|
|
}
|
|
} else if (ob_is_uint_tc(in_val.get_type())) {
|
|
uint64_t uint64_val = 0;
|
|
if (OB_FAIL(check_and_convert_uint_tc_value(in_val, (1LL << 32), uint64_val))) {
|
|
if (OB_ERR_WRONG_VALUE_FOR_VAR == ret) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
} else {}
|
|
} else {
|
|
LOG_WARN("fail to check uint tc value", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
sql_mode = uint64_val;
|
|
}
|
|
} else if (is_oracle_mode() && (ObNumberType == in_val.get_type())) {
|
|
number::ObNumber num = in_val.get_number();
|
|
uint64_t int_val = 0;
|
|
if (num.is_valid_uint64(int_val)) {
|
|
ObObj tmp_val;
|
|
tmp_val.set_uint64(int_val);
|
|
if (OB_FAIL(check_and_convert_uint_tc_value(tmp_val, (1LL << 32), int_val))) {
|
|
if (OB_ERR_WRONG_VALUE_FOR_VAR == ret) {
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, in_val))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(in_val));
|
|
} else {}
|
|
} else {
|
|
LOG_WARN("fail to check uint tc value", K(ret), K(in_val));
|
|
}
|
|
} else {
|
|
sql_mode = int_val;
|
|
}
|
|
} else {
|
|
ret = OB_ERR_WRONG_TYPE_FOR_VAR;
|
|
LOG_WARN("not valid int value for var on oracle mode", K(in_val));
|
|
}
|
|
} else {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid type for ObTypeLibSysVar", K(ret), K(in_val));
|
|
}
|
|
// check if valid
|
|
if (OB_SUCC(ret)) {
|
|
if (!is_sql_mode_supported(sql_mode)) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Value for sql_mode");
|
|
} else {
|
|
out_val.set_uint64(sql_mode);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_timestamp_service(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(sys_var);
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("session or sql_proxy is NULL", K(ret), KP(session));
|
|
} else {
|
|
// 创建租户时,actual_tenant_id_的值为UINT64_MAX
|
|
uint64_t tenant_id = set_var.actual_tenant_id_;
|
|
// if (tenant_id == OB_SYS_TENANT_ID) {
|
|
// if (ObIntType != in_val.get_type()) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("invalid type", K(ret), K(in_val.get_type()));
|
|
// } else {
|
|
// int64_t ts_type_idx = in_val.get_int();
|
|
// 系统租户下,系统变量ob_timestamp_service只能为LTS(0)
|
|
// if (0 != ts_type_idx) {
|
|
// ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
// ObString in_str = ObString(ObSysVarObTimestampService::OB_TIMESTAMP_SERVICE_NAMES[ts_type_idx]);
|
|
// LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, set_var.var_name_.length(), set_var.var_name_.ptr(),
|
|
// in_str.length(), in_str.ptr());
|
|
// }
|
|
// }
|
|
// } else {
|
|
out_val = in_val;
|
|
// }
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_max_allowed_packet(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(check_session_readonly(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check session readonly", K(ret), K(set_var), K(in_val));
|
|
} else if (set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
ObObj g_net_buffer_length_obj;
|
|
int64_t g_net_buffer_length = 0;
|
|
int64_t max_allowed_pkt = 0;
|
|
ObIAllocator &allocator = ctx.get_allocator();
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("session or sql_proxy is NULL", K(ret), KP(session));
|
|
} else if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(
|
|
session, allocator, ObString(OB_SV_NET_BUFFER_LENGTH),
|
|
g_net_buffer_length_obj))) {
|
|
LOG_WARN("fail to get global sys var: net_buffer_length",
|
|
K(ret), K(set_var), K(sys_var), K(in_val));
|
|
} else if (OB_FAIL(g_net_buffer_length_obj.get_int(g_net_buffer_length))) {
|
|
LOG_WARN("fail to get net_buffer_length int64", K(ret), K(set_var), K(sys_var),
|
|
K(in_val), K(g_net_buffer_length_obj));
|
|
} else if (OB_FAIL(in_val.get_int(max_allowed_pkt))) {
|
|
LOG_WARN("fail to get max_allowed_packet int64", K(ret), K(set_var), K(sys_var), K(in_val));
|
|
} else if (max_allowed_pkt < g_net_buffer_length) {
|
|
LOG_USER_WARN(OB_WARN_OPTION_BELOW_LIMIT, "max_allowed_packet", "net_buffer_length");
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_net_buffer_length(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(check_session_readonly(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check session readonly", K(ret), K(set_var), K(in_val));
|
|
} else if (set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
ObObj g_max_allowed_packet_obj;
|
|
int64_t g_max_allowed_packet = 0;
|
|
int64_t net_buffer_len = 0;
|
|
ObIAllocator &allocator = ctx.get_allocator();
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("session or sql_proxy is NULL", K(ret), KP(session));
|
|
} else if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(
|
|
session, allocator, ObString(OB_SV_MAX_ALLOWED_PACKET),
|
|
g_max_allowed_packet_obj))) {
|
|
LOG_WARN("fail to get global sys var: max_allowed_packet",
|
|
K(ret), K(set_var), K(sys_var), K(in_val));
|
|
} else if (OB_FAIL(g_max_allowed_packet_obj.get_int(g_max_allowed_packet))) {
|
|
LOG_WARN("fail to get max_allowed_packet int64", K(ret), K(set_var), K(sys_var),
|
|
K(in_val), K(g_max_allowed_packet_obj));
|
|
} else if (OB_FAIL(in_val.get_int(net_buffer_len))) {
|
|
LOG_WARN("fail to get net_buffer_length int64", K(ret), K(set_var), K(sys_var), K(in_val));
|
|
} else if (net_buffer_len > g_max_allowed_packet) {
|
|
LOG_USER_WARN(OB_WARN_OPTION_BELOW_LIMIT, "max_allowed_packet", "net_buffer_length");
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_charset(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
ObString cs_name;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (true == in_val.is_null()) {
|
|
// do nothing
|
|
} else {
|
|
ObString cs_name;
|
|
if (ObVarcharType == in_val.get_type()) {
|
|
cs_name = in_val.get_varchar();
|
|
ObCharsetType cs_type = CHARSET_INVALID;
|
|
ObCollationType coll_type = CS_TYPE_INVALID;
|
|
if (CHARSET_INVALID == (cs_type = ObCharset::charset_type(cs_name))) {
|
|
ret = OB_ERR_UNKNOWN_CHARSET;
|
|
LOG_USER_ERROR(OB_ERR_UNKNOWN_CHARSET, cs_name.length(), cs_name.ptr());
|
|
} else if (OB_UNLIKELY(CS_TYPE_INVALID == (coll_type =
|
|
ObCharset::get_default_collation(cs_type)))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("charset is valid, but it has no default collation", K(ret),
|
|
K(cs_name), K(cs_type));
|
|
} else {
|
|
out_val.set_int(static_cast<int64_t>(coll_type));
|
|
}
|
|
} else if (ObIntType == in_val.get_type()) {
|
|
int64_t int64_val = in_val.get_int();
|
|
if (false == ObCharset::is_valid_collation(int64_val)) {
|
|
ret = OB_ERR_UNKNOWN_CHARSET;
|
|
int p_ret = OB_SUCCESS;
|
|
const static int64_t val_buf_len = 1024;
|
|
char val_buf[val_buf_len];
|
|
int64_t pos = 0;
|
|
if (OB_SUCCESS != (p_ret = databuff_printf(val_buf, val_buf_len, pos, "%ld", int64_val))) {
|
|
// p_ret不覆盖ret
|
|
LOG_WARN("fail to databuff_printf", K(ret), K(p_ret), K(int64_val));
|
|
} else {
|
|
ObString cs_name_str(val_buf);
|
|
LOG_USER_ERROR(OB_ERR_UNKNOWN_CHARSET, cs_name_str.length(), cs_name_str.ptr());
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
} else {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_ERROR("invalid type", K(ret), K(in_val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_charset_not_null(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
ObString cs_name;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (true == in_val.is_null()) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, sys_var.get_name().length(), sys_var.get_name().ptr(),
|
|
(int)strlen("NULL"), "NULL");
|
|
} else if (OB_FAIL(check_and_convert_charset(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check and convert charset", K(ret), K(set_var), K(sys_var), K(in_val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_collation_not_null(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (true == in_val.is_null()) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, sys_var.get_name().length(), sys_var.get_name().ptr(),
|
|
(int)strlen("NULL"), "NULL");
|
|
} else {
|
|
ObString coll_name;
|
|
if (ObVarcharType == in_val.get_type()) {
|
|
coll_name = in_val.get_varchar();
|
|
ObCollationType coll_type = CS_TYPE_INVALID;
|
|
if (CS_TYPE_INVALID == (coll_type = ObCharset::collation_type(coll_name))) {
|
|
ret = OB_ERR_UNKNOWN_COLLATION;
|
|
LOG_USER_ERROR(OB_ERR_UNKNOWN_COLLATION, coll_name.length(), coll_name.ptr());
|
|
} else {
|
|
out_val.set_int(static_cast<int64_t>(coll_type));
|
|
}
|
|
} else if (ObIntType == in_val.get_type()) {
|
|
int64_t int64_val = in_val.get_int();
|
|
if (false == ObCharset::is_valid_collation(int64_val)) {
|
|
ret = OB_ERR_UNKNOWN_COLLATION;
|
|
int p_ret = OB_SUCCESS;
|
|
const static int64_t val_buf_len = 1024;
|
|
char val_buf[val_buf_len];
|
|
int64_t pos = 0;
|
|
if (OB_SUCCESS != (p_ret = databuff_printf(val_buf, val_buf_len, pos, "%ld", int64_val))) {
|
|
// p_ret不覆盖ret
|
|
LOG_WARN("fail to databuff_printf", K(ret), K(p_ret), K(int64_val));
|
|
} else {
|
|
ObString coll_name_str(val_buf);
|
|
LOG_USER_ERROR(OB_ERR_UNKNOWN_COLLATION, coll_name_str.length(), coll_name_str.ptr());
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
} else {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_ERROR("invalid type", K(ret), K(in_val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_timeout_too_large(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
UNUSED(set_var);
|
|
UNUSED(sys_var);
|
|
|
|
int ret = OB_SUCCESS;
|
|
int64_t timeout_val = 0;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (OB_FAIL(in_val.get_int(timeout_val))) {
|
|
} else if (timeout_val > OB_MAX_USER_SPECIFIED_TIMEOUT) {
|
|
out_val.set_int(OB_MAX_USER_SPECIFIED_TIMEOUT);
|
|
LOG_USER_WARN(OB_ERR_TIMEOUT_TRUNCATED);
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_tx_isolation(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
int32_t isolation = ObTransIsolation::get_level(in_val.get_string());
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get session info", K(ret));
|
|
} else if (!can_set_trans_var(set_var.set_scope_, *session)) {
|
|
ret = OB_ERR_CANT_CHANGE_TX_CHARACTERISTICS;
|
|
LOG_WARN("fail to check tx_isolation", K(ret),
|
|
K(set_var.set_scope_), K(session->get_trans_flags()));
|
|
} else if (ObTransIsolation::UNKNOWN == isolation) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
|
|
set_var.var_name_.length(), set_var.var_name_.ptr(),
|
|
in_val.get_string().length(), in_val.get_string().ptr());
|
|
LOG_WARN("invalid tx_isolation value", K(ret));
|
|
} else if (ObTransIsolation::READ_UNCOMMITTED == isolation) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED,
|
|
"Isolation level READ-UNCOMMITTED");
|
|
LOG_WARN("isolation level read-uncommitted not supported", K(ret), K(in_val));
|
|
} else {
|
|
if (OB_FAIL(ob_write_obj(ctx.get_allocator(), in_val, out_val))) {
|
|
LOG_WARN("deep copy out_val obj failed", K(ret));
|
|
}
|
|
ObString tmp_out_val = out_val.get_string();
|
|
if (OB_FAIL(ob_simple_low_to_up(ctx.get_allocator(),
|
|
in_val.get_string(),
|
|
tmp_out_val))) {
|
|
LOG_WARN("Isolation level change to upper string failed", K(ret));
|
|
}
|
|
out_val.set_varchar(tmp_out_val);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_tx_read_only(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get session info", K(ret));
|
|
} else if (!can_set_trans_var(set_var.set_scope_, *session)) {
|
|
ret = OB_ERR_CANT_CHANGE_TX_CHARACTERISTICS;
|
|
LOG_WARN("fail to check tx_read only", K(ret),
|
|
K(set_var.set_scope_), K(session->get_trans_flags()));
|
|
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_update_resource_manager_plan(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &val,
|
|
common::ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
ObString plan;
|
|
if (set_var.set_scope_== ObSetVar::SET_SCOPE_GLOBAL) {
|
|
if (val.is_null()) {
|
|
// maybe NULL, do nothing
|
|
} else if (OB_FAIL(val.get_string(plan))) {
|
|
LOG_WARN("fail to get sql mode str", K(ret), K(val), K(sys_var));
|
|
} else if (0 == plan.length()) {
|
|
// do nothing.
|
|
} else {
|
|
// check if plan exists
|
|
ObResourceManagerProxy proxy;
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get session info", K(ret));
|
|
} else {
|
|
uint64_t tenant_id = session->get_effective_tenant_id();
|
|
bool exists = false;
|
|
if (OB_FAIL(proxy.check_if_plan_exist(tenant_id, plan, exists))) {
|
|
LOG_WARN("fail check plan exists", K(tenant_id), K(plan), K(val), K(ret));
|
|
} else if (!exists) {
|
|
ret = OB_ERR_RES_MGR_PLAN_NOT_EXIST;
|
|
LOG_USER_ERROR(OB_ERR_RES_MGR_PLAN_NOT_EXIST);
|
|
LOG_WARN("plan not exist", K(plan), K(ret));
|
|
}
|
|
}
|
|
}
|
|
LOG_INFO("update resource manager plan", K(val), K(ret), K(set_var), K(sys_var));
|
|
}
|
|
out_val = val;
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_log_row_value_option_is_valid(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString val = in_val.get_string();
|
|
if (!val.empty()) {
|
|
if (val.case_compare("partial_lob") != 0) {
|
|
ret = OB_ERR_PARAM_VALUE_INVALID;
|
|
LOG_USER_ERROR(OB_ERR_PARAM_VALUE_INVALID);
|
|
} else {
|
|
// because not adapat obcdc, currently partial_lob is disabled
|
|
// out_val = in_val;
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("partial_lob is not support, please use _enable_dbms_lob_partial_update instead", K(ret), K(in_val));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "partial_lob");
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_default_lob_inrow_threshold(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t inrow_threshold = 0;
|
|
if (OB_FAIL(in_val.get_int(inrow_threshold))) {
|
|
LOG_WARN("get_int fail", K(ret), K(in_val));
|
|
} else if (inrow_threshold < OB_MIN_LOB_INROW_THRESHOLD || inrow_threshold > OB_MAX_LOB_INROW_THRESHOLD) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("lob inrow_threshold invalid", KR(ret), K(inrow_threshold));
|
|
// error msg to user
|
|
int tmp_ret = OB_SUCCESS;
|
|
const int64_t ERROR_MSG_LENGTH = 256;
|
|
char error_msg[ERROR_MSG_LENGTH] = "";
|
|
int64_t pos = 0;
|
|
if (OB_SUCCESS != (tmp_ret = databuff_printf(error_msg, ERROR_MSG_LENGTH,
|
|
pos, "lob inrow threshold, should be [%ld, %ld]", OB_MIN_LOB_INROW_THRESHOLD, OB_MAX_LOB_INROW_THRESHOLD))) {
|
|
LOG_WARN("print error msg fail", K(ret), K(tmp_ret), K(error_msg), K(pos));
|
|
} else {
|
|
LOG_USER_ERROR(OB_INVALID_ARGUMENT, error_msg);
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObSysVarOnCheckFuncs::can_set_trans_var(ObSetVar::SetScopeType scope,
|
|
ObBasicSessionInfo &session)
|
|
{
|
|
bool ret = false;
|
|
if (lib::is_oracle_mode()) {
|
|
/*
|
|
* in oracle, isolation = SERIALIZABLE:
|
|
* 1. statement may get a snapshot and read it without any transaction,
|
|
* create new snapshot if there is no current snapshot, otherwise
|
|
* reuse current snapshot generated by the previous statement.
|
|
* 2. statement need a transaction ONLY IF it needs lock row,
|
|
* create new transaction if there is no current transaction, otherwise
|
|
* reuse current transaction generated by the previous statement.
|
|
* 3. 'SET TRANSACTION xxx' will ALWAYS release current snapshot (if exists),
|
|
* then create new snapshot, but it will cause error in any of these cases:
|
|
* a. the current snapshot is generated by previous 'SET TRANSACTION xxx', or
|
|
* b. the current snapshot is in transaction.
|
|
* 4. 'ALTER SESSION SET isolation_level' will ALWAYS release current snapshot
|
|
* (if exists), then modify the 'isolation_level' value in session, but it
|
|
* will cause error in any of these cases:
|
|
* a. the current snapshot is generated by previous 'SET TRANSACTION xxx'.
|
|
*
|
|
* since OB 4.0, transaction's model very like to Oracle's and we can handle
|
|
* these transaction characteristics modifiy stmt more simply.
|
|
*
|
|
* in previouse version OB:
|
|
* the most problem is: every snapshot must base on a transaction, create
|
|
* new snapshot means create new transaction too. so we need some extra flags to
|
|
* record some informations:
|
|
* 1. has_set_trans_var: whether the current transaction is generated by 'SET TRANSACTION xxx',
|
|
* for oracle rule 3-a and 4-a.
|
|
* 2. has_hold_row_lock: whether the current transaction hold row lock,
|
|
* for oracle rule 3-b.
|
|
* ps: SET_SCOPE_GLOBAL could not appear in oracle mode, so we need not care scope
|
|
* because SET_SCOPE_SESSION and SET_SCOPE_NEXT_TRANS have same behavior in this
|
|
* function.
|
|
* see:
|
|
*
|
|
*
|
|
*/
|
|
ret = !session.is_in_transaction() || session.is_txn_free_route_temp();
|
|
} else if (lib::is_mysql_mode()) {
|
|
/*
|
|
* mysql mode is much simpler than oracle mode, only 'SET TRANSACTION xxx' is forbidden
|
|
* when it appears in an explicit transaction, and it will not create new snapshot or
|
|
* transaction in all cases.
|
|
*/
|
|
ret = !session.is_in_transaction() || ObSetVar::SET_SCOPE_NEXT_TRANS != scope;
|
|
} else {
|
|
// nothing.
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_max_user_connections(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
return check_session_readonly(ctx, set_var, sys_var, in_val, out_val);
|
|
}
|
|
|
|
//#define MAX_MODE_STR_BUF_LEN 512
|
|
int ObSysVarOnCheckFuncs::check_and_convert_sql_mode(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(ctx);
|
|
UNUSED(set_var);
|
|
UNUSED(sys_var);
|
|
UNUSED(in_val);
|
|
UNUSED(out_val);
|
|
//todo , according to mysql
|
|
//check the sql_mode is to be discard;
|
|
/*if (true == set_var.is_set_default_) {
|
|
//nothing to do
|
|
} else {
|
|
char *buf = reinterpret_cast<char*>(ctx.get_allocator().alloc(MAX_MODE_STR_BUF_LEN));
|
|
if (false == ob_is_string_type(out_val.get_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
SQL_SESSION_LOG(WARN, "invalid argument, sql_mode out_val should be string type", K(out_val));
|
|
} else if (NULL == buf) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
SQL_SESSION_LOG(ERROR, "failed to alloc memory", K(ret));
|
|
} else {
|
|
ObString sql_mode_str = out_val.get_string();
|
|
char *end_ptr = buf;
|
|
if (0 == sql_mode_str.case_compare(STR_ANSI)) {
|
|
snprintf(buf, MAX_MODE_STR_BUF_LEN, "%s", STR_COMBINE_ANSI);
|
|
end_ptr += strlen(STR_COMBINE_ANSI);
|
|
ObString out_str;
|
|
out_str.assign_ptr(buf, static_cast<int32_t>(end_ptr - buf));
|
|
out_val.set_varchar(out_str);
|
|
} else if (0 == sql_mode_str.case_compare(STR_TRADITIONAL)) {
|
|
snprintf(buf, MAX_MODE_STR_BUF_LEN, "%s", STR_COMBINE_TRADITIONAL);
|
|
end_ptr += strlen(STR_COMBINE_TRADITIONAL);
|
|
ObString out_str;
|
|
out_str.assign_ptr(buf, static_cast<int32_t>(end_ptr - buf));
|
|
out_val.set_varchar(out_str);
|
|
}
|
|
}
|
|
}*/
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_time_zone(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(ctx);
|
|
UNUSED(set_var);
|
|
UNUSED(sys_var);
|
|
UNUSED(in_val);
|
|
UNUSED(out_val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_max_min_timestamp(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
ObCastMode cast_mode = CM_NONE;
|
|
if (true == set_var.is_set_default_) {
|
|
//nothing to do
|
|
} else if (OB_FAIL(ObSQLUtils::get_default_cast_mode(ctx.get_my_session(), cast_mode))) {
|
|
LOG_WARN("failed to get cast_mode", K(ret));
|
|
} else if (in_val.get_number().is_negative() || in_val.get_number() >= TIMESTAMP_MAX_VAL) {
|
|
if (CM_WARN_ON_FAIL == cast_mode) {
|
|
const char *value = in_val.get_number().format();
|
|
LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, set_var.var_name_.length(),
|
|
set_var.var_name_.ptr(), static_cast<int32_t>(strlen(value)),
|
|
value);
|
|
common::number::ObNumber num;
|
|
num.set_zero();
|
|
out_val.set_number(num);
|
|
} else {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, set_var.var_name_.length(), set_var.var_name_.ptr(),
|
|
(int)strlen(in_val.get_number().format()), in_val.get_number().format());
|
|
}
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_ob_org_cluster_id(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(sys_var);
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (true == set_var.is_set_default_) { // 禁止set ob_org_cluster_id = default
|
|
ret = OB_ERR_NO_DEFAULT;
|
|
LOG_USER_ERROR(OB_ERR_NO_DEFAULT, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else if (true == in_val.is_null()) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, sys_var.get_name().length(), sys_var.get_name().ptr(),
|
|
(int)strlen("NULL"), "NULL");
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_sql_throttle_queue_time(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
UNUSED(set_var);
|
|
UNUSED(sys_var);
|
|
|
|
int ret = OB_SUCCESS;
|
|
number::ObNumber num;
|
|
char buf[32] = {};
|
|
int64_t pos = 0;
|
|
double lower = .0;
|
|
if (true == set_var.is_set_default_) {
|
|
// do nothing
|
|
} else if (OB_FAIL(in_val.get_number(num))) {
|
|
} else if (OB_FAIL(num.format(buf, sizeof (buf), pos, 6))) {
|
|
} else if (pos >= sizeof (buf)) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
} else if (FALSE_IT(lower = atof(buf))) {
|
|
} else if (lower < 0.001 && num != -1l) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, sys_var.get_name().length(), sys_var.get_name().ptr(),
|
|
static_cast<int>(strlen("NULL")), "NULL");
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_nls_currency_too_long(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(check_session_readonly(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check session readonly", K(ret), K(set_var), K(in_val));
|
|
} else if (set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
const int32_t MAX_NLS_CURRENCY_LEN = 10;
|
|
ObString in_nls_currency_str = in_val.get_string();
|
|
if (in_nls_currency_str.length() <= MAX_NLS_CURRENCY_LEN) {
|
|
out_val = in_val;
|
|
} else {
|
|
ObString out_nls_currency_str;
|
|
ObIAllocator &allocator = ctx.get_allocator();
|
|
if (OB_FAIL(ob_write_string(allocator, in_nls_currency_str, out_nls_currency_str))) {
|
|
LOG_WARN("failed to write stirng", K(ret));
|
|
} else {
|
|
out_nls_currency_str.assign_ptr(out_nls_currency_str.ptr(), MAX_NLS_CURRENCY_LEN);
|
|
out_val.set_varchar(out_nls_currency_str);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_nls_iso_currency_is_valid(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(check_session_readonly(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check session readonly", K(ret), K(set_var), K(in_val));
|
|
} else if (set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
ObString in_country_str = in_val.get_string();
|
|
ObString out_country_str;
|
|
ObIAllocator &allocator = ctx.get_allocator();
|
|
if (OB_FAIL(ob_simple_low_to_up(allocator, in_country_str, out_country_str))) {
|
|
LOG_WARN("failed to write stirng", K(ret));
|
|
} else {
|
|
if (!IsoCurrencyUtils::is_country_valid(out_country_str)) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_WARN("failed to get currency by country name", K(ret));
|
|
} else {
|
|
out_val.set_varchar(out_country_str);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_nls_length_semantics_is_valid(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(check_session_readonly(ctx, set_var, sys_var, in_val, out_val))) {
|
|
LOG_WARN("fail to check session readonly", K(ret), K(set_var), K(in_val));
|
|
} else if (set_var.is_set_default_) {
|
|
// do nothing
|
|
} else {
|
|
ObString str_val;
|
|
ObLengthSemantics nls_length_semantics = LS_INVALIED;
|
|
OZ (in_val.get_string(str_val));
|
|
OX (nls_length_semantics = get_length_semantics(str_val));
|
|
OV (nls_length_semantics != LS_INVALIED,
|
|
OB_ERR_CANNOT_ACCESS_NLS_DATA_FILES_OR_INVALID_ENVIRONMENT_SPECIFIED, nls_length_semantics);
|
|
OX (out_val = in_val);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_session_readonly(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &in_val,
|
|
ObObj &out_val)
|
|
{
|
|
UNUSED(ctx);
|
|
int ret = OB_SUCCESS;
|
|
if (ObSetVar::SET_SCOPE_SESSION == set_var.set_scope_ && true == sys_var.is_session_readonly()) {
|
|
ret = OB_ERR_VARIABLE_IS_READONLY;
|
|
LOG_USER_ERROR(OB_ERR_VARIABLE_IS_READONLY, (int)strlen("SESSION"), "SESSION",
|
|
sys_var.get_name().length(), sys_var.get_name().ptr(),
|
|
(int)strlen("GLOBAL"), "GLOBAL");
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_locale_type_is_valid(
|
|
sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "lc_time_names");
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_plsql_warnings(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
#ifndef OB_BUILD_ORACLE_PL
|
|
UNUSEDx(ctx, set_var, sys_var, in_val, out_val);
|
|
#else
|
|
UNUSEDx(ctx, set_var, sys_var);
|
|
if (OB_FAIL(pl::PlCompilerWarningCategory::verify_warning_settings(in_val.get_string(), NULL))) {
|
|
ret = OB_ERR_PARAM_VALUE_INVALID;
|
|
LOG_USER_ERROR(OB_ERR_PARAM_VALUE_INVALID);
|
|
} else {
|
|
out_val = in_val;
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_and_convert_plsql_ccflags(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSEDx(ctx, set_var, sys_var, out_val);
|
|
OZ (ObExprPLSQLVariable::check_plsql_ccflags(in_val.get_string()));
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::get_string(const ObObj &val, ObString &str)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ObCharType == val.get_type()) {
|
|
str = val.get_string();
|
|
} else if (ObVarcharType == val.get_type()) {
|
|
str = val.get_varchar();
|
|
} else {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_ERROR("invalid type", K(ret), K(val));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnCheckFuncs::check_runtime_filter_type_is_valid(
|
|
sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &in_val,
|
|
common::ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString str_val;
|
|
if (OB_FAIL(in_val.get_varchar(str_val))) {
|
|
LOG_WARN("fail to get varchar", K(ret), K(in_val));
|
|
} else {
|
|
int64_t rf_type = ObConfigRuntimeFilterChecker::get_runtime_filter_type(str_val.ptr(),
|
|
str_val.length());
|
|
if (rf_type >= 0) {
|
|
out_val = in_val;
|
|
} else {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, str_val.length(), str_val.ptr(), str_val.length(), str_val.ptr());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnUpdateFuncs::update_tx_isolation(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
const ObString &var_name = set_var.var_name_;
|
|
const ObString &var_val = val.get_string();
|
|
ObTxIsolationLevel isolation = transaction::tx_isolation_from_str(var_val);
|
|
bool for_next_trans = (set_var.set_scope_ == ObSetVar::SET_SCOPE_NEXT_TRANS);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get session info", K(ret));
|
|
} else if (ObTxIsolationLevel::INVALID == isolation) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
|
|
var_name.length(), var_name.ptr(), var_val.length(), var_val.ptr());
|
|
LOG_WARN("isolation level is invalid", K(ret), K(var_val), K(var_name));
|
|
} else if (ObTxIsolationLevel::RU == isolation) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED,
|
|
"Isolation level READ-UNCOMMITTED");
|
|
LOG_WARN("isolation level read-uncommitted not supported", K(ret), K(var_val), K(var_name));
|
|
} else if (for_next_trans && FALSE_IT(session->set_tx_isolation(isolation))) {
|
|
// nothing.
|
|
} else if (lib::is_oracle_mode()) {
|
|
if (for_next_trans) {
|
|
/*
|
|
* 'SET TRANSACTION xxx' will ALWAYS create new snapshot in oracle
|
|
* see comments in can_set_trans_var() for more details.
|
|
* ps: read only can't be 'ALTER SESSION SET' in oracle, so use default value false.
|
|
*/
|
|
session->set_tx_isolation(isolation);
|
|
// tx must be ilde, previouse check `can_set_trans_var` has check this
|
|
if (OB_FAIL(start_trans_by_set_trans_char_(ctx))) {
|
|
// TODO: fatal bug, need disconnect
|
|
LOG_WARN("auto start trans fail when set txn charactor", K(ret),
|
|
KPC(session->get_tx_desc()), KPC(session));
|
|
}
|
|
} else {
|
|
/*
|
|
* 'ALTER SESSION SET isolation_level' just release snapshot since 4.0
|
|
* previouse check in can_set_trans_var promise no active trans in current session
|
|
*/
|
|
if (ObTxIsolationLevel::SERIAL == isolation ||
|
|
ObTxIsolationLevel::RR == isolation) {
|
|
// release snapshot, following stmt will acquire snapshot again
|
|
if (!session->is_txn_free_route_temp() &&
|
|
OB_NOT_NULL(session->get_tx_desc()) &&
|
|
OB_FAIL(MTL(transaction::ObTransService*)
|
|
->release_snapshot(*session->get_tx_desc()))) {
|
|
TRANS_LOG(WARN, "try to release snapshot for current session fail",
|
|
K(ret), KPC(session->get_tx_desc()));
|
|
// TODO: fatal bug, need disconnect
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int ObSysVarOnUpdateFuncs::update_tx_read_only_no_scope(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const ObObj &val)
|
|
{
|
|
UNUSED(sys_var);
|
|
int ret = OB_SUCCESS;
|
|
if (set_var.set_scope_ == ObSetVar::SET_SCOPE_NEXT_TRANS) {
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
const bool read_only = val.get_bool();
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("fail to get session info", K(ret));
|
|
} else if (FALSE_IT(session->set_tx_read_only(!read_only, read_only))) {
|
|
// nothing.
|
|
} else if (lib::is_oracle_mode()) {
|
|
// READ ONLY will use SERIALIZABLE implicitly,
|
|
// READ WRITE need use default value in session, so set UNKNOWN.
|
|
//
|
|
// if read only, set tx isolation level to serializable
|
|
// otherwise, use the value in session
|
|
if (read_only) {
|
|
session->set_tx_isolation(ObTxIsolationLevel::SERIAL);
|
|
}
|
|
if (OB_FAIL(start_trans_by_set_trans_char_(ctx))) {
|
|
// TODO: fatal bug, need disconnect
|
|
LOG_WARN("auto start trans fail when set txn charactor", K(ret),
|
|
KPC(session->get_tx_desc()), KPC(session));
|
|
}
|
|
}
|
|
LOG_DEBUG("update tx_read only, while scope=none", K(ret), K(val.get_bool()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnUpdateFuncs::start_trans_by_set_trans_char_(
|
|
sql::ObExecContext &ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
auto &session = *GET_MY_SESSION(ctx);
|
|
auto isolation = session.get_tx_isolation();
|
|
if (OB_FAIL(ObSqlTransControl::explicit_start_trans(ctx,
|
|
session.get_tx_read_only()))) {
|
|
LOG_WARN("fail to start trans", K(ret));
|
|
} else if (ObTxIsolationLevel::SERIAL == isolation ||
|
|
ObTxIsolationLevel::RR == isolation) {
|
|
int64_t query_timeout = 0;
|
|
session.get_query_timeout(query_timeout);
|
|
int64_t stmt_expire_ts = session.get_query_start_time() + query_timeout;
|
|
transaction::ObTxReadSnapshot snapshot;
|
|
if (OB_FAIL(MTL(transaction::ObTransService*)
|
|
->get_read_snapshot(*session.get_tx_desc(),
|
|
isolation,
|
|
stmt_expire_ts,
|
|
snapshot))) {
|
|
LOG_WARN("fail to get snapshot for serializable / repeatable read", K(ret),
|
|
KPC(session.get_tx_desc()), K(isolation), K(stmt_expire_ts));
|
|
// rollback tx because of prepare snapshot fail
|
|
int save_ret = ret;
|
|
if (OB_FAIL(ObSqlTransControl::end_trans(ctx, true, true, NULL))) {
|
|
LOG_WARN("rollback tx fail", K(ret), KPC(session.get_tx_desc()));
|
|
}
|
|
// rollback tx fail, need report to user, because session is corrupt
|
|
ret = COVER_SUCC(save_ret);
|
|
} else {
|
|
LOG_TRACE("succeed get snapshot for oracle set trans charactor stmt",
|
|
KPC(session.get_tx_desc()), K(isolation), K(snapshot));
|
|
}
|
|
} else {
|
|
LOG_TRACE("set trans charactor done for RC isolation",
|
|
K(isolation), KPC(session.get_tx_desc()));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarOnUpdateFuncs::update_sql_mode(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &val)
|
|
{
|
|
UNUSED(ctx);
|
|
UNUSED(sys_var);
|
|
UNUSED(val);
|
|
int ret = OB_SUCCESS;
|
|
if (set_var.set_scope_== ObSetVar::SET_SCOPE_GLOBAL) {
|
|
//nothing to do
|
|
} else {
|
|
//处理MODE_NO_BACKSLASH_ESCAPES
|
|
//是否将反斜杠作为转义符。保存在系统变量中,
|
|
//暂时不支持。
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObSysVarOnUpdateFuncs::update_safe_weak_read_snapshot(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObBasicSysVar &sys_var,
|
|
const common::ObObj &val)
|
|
{
|
|
UNUSED(ctx);
|
|
UNUSED(set_var);
|
|
UNUSED(sys_var);
|
|
UNUSED(val);
|
|
return OB_SUCCESS;
|
|
}
|
|
|
|
int ObSysVarToObjFuncs::to_obj_charset(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObObj &result_obj)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString result_str;
|
|
if (ObNullType == sys_var.get_value().get_type()) {
|
|
result_obj.set_null();
|
|
} else if (OB_FAIL(ObSysVarToStrFuncs::to_str_charset(allocator, session, sys_var, result_str))) {
|
|
LOG_WARN("fail to convert to str charset", K(ret), K(sys_var));
|
|
} else {
|
|
result_obj.set_varchar(result_str);
|
|
result_obj.set_collation_type(ObCharset::get_system_collation());
|
|
result_obj.set_collation_level(sys_var.get_value().get_collation_level());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarToObjFuncs::to_obj_collation(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObObj &result_obj)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString result_str;
|
|
if (ObNullType == sys_var.get_value().get_type()) {
|
|
result_obj.set_null();
|
|
} else if (OB_FAIL(ObSysVarToStrFuncs::to_str_collation(
|
|
allocator, session, sys_var, result_str))) {
|
|
LOG_WARN("fail to convert to str collation", K(ret), K(sys_var));
|
|
} else {
|
|
result_obj.set_varchar(result_str);
|
|
result_obj.set_collation_type(ObCharset::get_system_collation());
|
|
result_obj.set_collation_level(sys_var.get_value().get_collation_level());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarToObjFuncs::to_obj_sql_mode(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObObj &result_obj)
|
|
{
|
|
UNUSED(session);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ob_sql_mode_to_str(sys_var.get_value(), result_obj, &allocator))) {
|
|
LOG_WARN("fail to convert sql mode to str", K(ret), K(sys_var));
|
|
} else {
|
|
result_obj.set_collation_type(ObCharset::get_system_collation());
|
|
result_obj.set_collation_level(sys_var.get_value().get_collation_level());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarToStrFuncs::to_str_charset(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObString &result_str)
|
|
{
|
|
UNUSED(allocator);
|
|
UNUSED(session);
|
|
int ret = OB_SUCCESS;
|
|
int64_t coll_type_int64 = -1;
|
|
if (ObNullType == sys_var.get_value().get_type()) {
|
|
result_str = ObString("");
|
|
} else if (OB_FAIL(sys_var.get_value().get_int(coll_type_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid value", K(ret), K(sys_var), K(sys_var.get_value()));
|
|
} else if (coll_type_int64 == 0) {
|
|
result_str = ObString("");
|
|
} else if (OB_UNLIKELY(false == ObCharset::is_valid_collation(coll_type_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid collation", K(ret), K(coll_type_int64), K(sys_var));
|
|
} else if (OB_FAIL(ObCharset::charset_name_by_coll(
|
|
static_cast<ObCollationType>(coll_type_int64), result_str))) {
|
|
LOG_WARN("fail to get charset name by collation type", K(ret), K(coll_type_int64));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarToStrFuncs::to_str_collation(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObString &result_str)
|
|
{
|
|
UNUSED(allocator);
|
|
UNUSED(session);
|
|
int ret = OB_SUCCESS;
|
|
int64_t coll_type_int64 = -1;
|
|
if (ObNullType == sys_var.get_value().get_type()) {
|
|
result_str = ObString("");
|
|
} else if (OB_FAIL(sys_var.get_value().get_int(coll_type_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid value", K(ret), K(sys_var), K(sys_var.get_value()));
|
|
} else if (OB_UNLIKELY(false == ObCharset::is_valid_collation(coll_type_int64))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("invalid collation", K(ret), K(coll_type_int64), K(sys_var));
|
|
} else {
|
|
const char *coll_name_str_ptr = ObCharset::collation_name(
|
|
static_cast<ObCollationType>(coll_type_int64));
|
|
result_str = ObString(coll_name_str_ptr);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarToStrFuncs::to_str_sql_mode(ObIAllocator &allocator,
|
|
const ObBasicSessionInfo &session,
|
|
const ObBasicSysVar &sys_var,
|
|
ObString &result_str)
|
|
{
|
|
UNUSED(session);
|
|
int ret = OB_SUCCESS;
|
|
ObObj str_obj;
|
|
if (OB_FAIL(ob_sql_mode_to_str(sys_var.get_value(), str_obj, &allocator))) {
|
|
LOG_WARN("fail to convert sql mode to str", K(ret), K(sys_var));
|
|
} else if (OB_FAIL(str_obj.get_varchar(result_str))) {
|
|
LOG_WARN("fail to get sql mode str", K(ret), K(str_obj), K(sys_var));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarSessionSpecialUpdateFuncs::update_identity(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(set_var.var_name_ != OB_SV_IDENTITY)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("var name must be OB_SV_IDENTITY", K(ret), K(set_var.var_name_),
|
|
K(OB_SV_IDENTITY), K(val));
|
|
} else if (true == set_var.is_set_default_) {
|
|
ret = OB_ERR_NO_DEFAULT;
|
|
LOG_USER_ERROR(OB_ERR_NO_DEFAULT, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else {
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_UNLIKELY(ObSetVar::SET_SCOPE_GLOBAL == set_var.set_scope_) ||
|
|
OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("identity or last_insert_id is session variable or session is NULL",
|
|
K(ret), K(set_var.var_name_), K(session));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_IDENTITY, val))) {
|
|
LOG_WARN("fail to update identity", K(ret), K(set_var.var_name_),
|
|
K(SYS_VAR_IDENTITY), K(val));
|
|
}
|
|
//同时update系统变量last_insert_id
|
|
else if (OB_FAIL(session->update_sys_variable(SYS_VAR_LAST_INSERT_ID, val))) {
|
|
LOG_WARN("succ to update identity, but fail to update last_insert_id",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_LAST_INSERT_ID), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarSessionSpecialUpdateFuncs::update_last_insert_id(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(set_var.var_name_ != OB_SV_LAST_INSERT_ID)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("var name must be OB_SV_LAST_INSERT_ID", K(ret), K(set_var.var_name_),
|
|
K(OB_SV_LAST_INSERT_ID), K(val));
|
|
} else if (true == set_var.is_set_default_) {
|
|
ret = OB_ERR_NO_DEFAULT;
|
|
LOG_USER_ERROR(OB_ERR_NO_DEFAULT, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else {
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (ObSetVar::SET_SCOPE_GLOBAL == set_var.set_scope_ ||
|
|
OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("identity or last_insert_id is session variableor session is NULL",
|
|
K(ret), K(set_var.var_name_), K(session));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_LAST_INSERT_ID, val))) {
|
|
LOG_WARN("fail to update last_insert_id", K(ret), K(set_var.var_name_),
|
|
K(OB_SV_LAST_INSERT_ID), K(val));
|
|
}
|
|
//同时update系统变量identity
|
|
else if (OB_FAIL(session->update_sys_variable(SYS_VAR_IDENTITY, val))) {
|
|
LOG_WARN("succ to update last_insert_id, but fail to update identity",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_IDENTITY), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarSessionSpecialUpdateFuncs::update_tx_isolation(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if ((OB_UNLIKELY(set_var.var_name_ != OB_SV_TX_ISOLATION))
|
|
&& (OB_UNLIKELY(set_var.var_name_ != OB_SV_TRANSACTION_ISOLATION))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("var name must be OB_SV_TX_ISOLATION or OB_SV_TRANSACTION_ISOLATION",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_TX_ISOLATION),
|
|
K(OB_SV_TRANSACTION_ISOLATION),K(val));
|
|
} else if (true == set_var.is_set_default_) {
|
|
ret = OB_ERR_NO_DEFAULT;
|
|
LOG_USER_ERROR(OB_ERR_NO_DEFAULT, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else {
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("session is NULL", K(ret), K(set_var.var_name_), K(session));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_TX_ISOLATION, val))) {
|
|
LOG_WARN("fail to update tx_isolation", K(ret), K(set_var.var_name_),
|
|
K(SYS_VAR_TX_ISOLATION), K(val));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_TRANSACTION_ISOLATION, val))) {
|
|
LOG_WARN("succ to update tx_isolation, but fail to update last_insert_id",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_TRANSACTION_ISOLATION), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarSessionSpecialUpdateFuncs::update_tx_read_only(sql::ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const common::ObObj &val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if ((OB_UNLIKELY(set_var.var_name_ != OB_SV_TX_READ_ONLY))
|
|
&& (OB_UNLIKELY(set_var.var_name_ != OB_SV_TRANSACTION_READ_ONLY))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("var name must be OB_SV_TX_READ_ONLY or OB_SV_TRANSACTION_READ_ONLY",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_TX_ISOLATION),
|
|
K(OB_SV_TRANSACTION_ISOLATION),K(val));
|
|
} else if (true == set_var.is_set_default_) {
|
|
ret = OB_ERR_NO_DEFAULT;
|
|
LOG_USER_ERROR(OB_ERR_NO_DEFAULT, set_var.var_name_.length(), set_var.var_name_.ptr());
|
|
} else {
|
|
ObSQLSessionInfo *session = GET_MY_SESSION(ctx);
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("session is NULL", K(ret), K(set_var.var_name_), K(session));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_TX_READ_ONLY, val))) {
|
|
LOG_WARN("fail to update tx_read_only", K(ret), K(set_var.var_name_),
|
|
K(SYS_VAR_TX_ISOLATION), K(val));
|
|
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_TRANSACTION_READ_ONLY, val))) {
|
|
LOG_WARN("succ to update tx_read_only, but fail to update transaction_read_only",
|
|
K(ret), K(set_var.var_name_), K(OB_SV_TRANSACTION_ISOLATION), K(val));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
|
|
ObCharsetSysVarPair ObCharsetSysVarPair::CHARSET_SYS_VAR_PAIRS[SYS_CHARSET_SYS_VAR_PAIR_COUNT] =
|
|
{
|
|
ObCharsetSysVarPair(OB_SV_CHARACTER_SET_SERVER, OB_SV_COLLATION_SERVER),
|
|
ObCharsetSysVarPair(OB_SV_CHARACTER_SET_DATABASE, OB_SV_COLLATION_DATABASE),
|
|
ObCharsetSysVarPair(OB_SV_CHARACTER_SET_CONNECTION, OB_SV_COLLATION_CONNECTION)
|
|
};
|
|
|
|
int ObCharsetSysVarPair::get_charset_var_by_collation_var(const ObString &coll_var_name,
|
|
ObString &cs_var_name)
|
|
{
|
|
int ret = OB_ENTRY_NOT_EXIST;
|
|
for (int64_t i = 0; OB_ENTRY_NOT_EXIST == ret && i < SYS_CHARSET_SYS_VAR_PAIR_COUNT; ++i) {
|
|
if (CHARSET_SYS_VAR_PAIRS[i].coll_var_name_ == coll_var_name) {
|
|
cs_var_name = CHARSET_SYS_VAR_PAIRS[i].cs_var_name_;
|
|
ret = OB_SUCCESS;
|
|
} else {}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObCharsetSysVarPair::get_collation_var_by_charset_var(const ObString &cs_var_name,
|
|
ObString &coll_var_name)
|
|
{
|
|
int ret = OB_ENTRY_NOT_EXIST;
|
|
for (int64_t i = 0; OB_ENTRY_NOT_EXIST == ret && i < SYS_CHARSET_SYS_VAR_PAIR_COUNT; ++i) {
|
|
if (CHARSET_SYS_VAR_PAIRS[i].cs_var_name_ == cs_var_name) {
|
|
coll_var_name = CHARSET_SYS_VAR_PAIRS[i].coll_var_name_;
|
|
ret = OB_SUCCESS;
|
|
} else {}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPreProcessSysVars::change_initial_value()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// OB_SV_VERSION_COMMENT
|
|
if (OB_FAIL(ObSysVariables::set_value(OB_SV_VERSION_COMMENT,
|
|
ObSpecialSysVarValues::version_comment_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_VERSION_COMMENT),
|
|
K(ObSpecialSysVarValues::version_comment_));
|
|
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_VERSION_COMMENT,
|
|
ObSpecialSysVarValues::version_comment_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_VERSION_COMMENT),
|
|
K(ObSpecialSysVarValues::version_comment_));
|
|
// OB_SV_SYSTEM_TIME_ZONE
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_SYSTEM_TIME_ZONE,
|
|
ObSpecialSysVarValues::system_time_zone_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_SYSTEM_TIME_ZONE),
|
|
K(ObSpecialSysVarValues::system_time_zone_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_SYSTEM_TIME_ZONE,
|
|
ObSpecialSysVarValues::system_time_zone_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_SYSTEM_TIME_ZONE),
|
|
K(ObSpecialSysVarValues::system_time_zone_str_));
|
|
// charset和collation相关
|
|
// OB_SV_CHARACTER_SET_SERVER
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_CHARACTER_SET_SERVER,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(ret), K(OB_SV_CHARACTER_SET_SERVER),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_CHARACTER_SET_SERVER,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(ret), K(OB_SV_CHARACTER_SET_SERVER),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_CHARACTER_SET_CONNECTION
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_CHARACTER_SET_CONNECTION,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_CONNECTION),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_CHARACTER_SET_CONNECTION,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_CONNECTION),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_CHARACTER_SET_CLIENT
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_CHARACTER_SET_CLIENT,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_CLIENT),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_CHARACTER_SET_CLIENT,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_CLIENT),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_CHARACTER_SET_RESULTS
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_CHARACTER_SET_RESULTS,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_RESULTS),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_CHARACTER_SET_RESULTS,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_RESULTS),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_CHARACTER_SET_SYSTEM
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_CHARACTER_SET_SYSTEM,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_SYSTEM),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_CHARACTER_SET_SYSTEM,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_CHARACTER_SET_SYSTEM),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_COLLATION_SERVER
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_COLLATION_SERVER,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_SERVER),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_COLLATION_SERVER,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_SERVER),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_COLLATION_DATABASE
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_COLLATION_DATABASE,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_DATABASE),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_COLLATION_DATABASE,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_DATABASE),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_COLLATION_CONNECTION
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_COLLATION_CONNECTION,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_CONNECTION),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_COLLATION_CONNECTION,
|
|
ObSpecialSysVarValues::default_coll_int_str_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_COLLATION_CONNECTION),
|
|
K(ObSpecialSysVarValues::default_coll_int_str_));
|
|
// OB_SV_SERVER_UUID
|
|
} else if (OB_FAIL(ObSysVariables::set_value(OB_SV_SERVER_UUID,
|
|
ObSpecialSysVarValues::server_uuid_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_SERVER_UUID),
|
|
K(ObSpecialSysVarValues::server_uuid_));
|
|
} else if (OB_FAIL(ObSysVariables::set_base_value(OB_SV_SERVER_UUID,
|
|
ObSpecialSysVarValues::server_uuid_))) {
|
|
LOG_WARN("fail to change initial value", K(OB_SV_SERVER_UUID),
|
|
K(ObSpecialSysVarValues::server_uuid_));
|
|
} else {
|
|
LOG_INFO("succ to change_initial_value",
|
|
"version_comment", ObSpecialSysVarValues::version_comment_,
|
|
"system_time_zone_str", ObSpecialSysVarValues::system_time_zone_str_,
|
|
"default_coll_int_str", ObSpecialSysVarValues::default_coll_int_str_,
|
|
"server_uuid", ObSpecialSysVarValues::server_uuid_);
|
|
}
|
|
return ret;
|
|
}
|
|
int ObPreProcessSysVars::init_sys_var()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(ObPreProcessSysVars::change_initial_value())) {
|
|
LOG_ERROR("fail to change initial value", K(ret));
|
|
} else if (OB_FAIL(ObSysVariables::init_default_values())) {
|
|
LOG_ERROR("fail to init default values", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSetSysVar::find_set(const ObString &str)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
char *buf = NULL;
|
|
if (str.length() <= 0) {
|
|
//nothing to do
|
|
} else if (OB_UNLIKELY(str.length() >= MAX_STR_BUF_LEN)) {
|
|
ret = OB_BUF_NOT_ENOUGH;
|
|
LOG_WARN("system variable string is too long", K(ret), K(str));
|
|
} else if (OB_ISNULL(buf = strndupa(str.ptr(), str.length()))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("failed to alloc memory", K(ret));
|
|
} else {
|
|
char *value = NULL;
|
|
char *saveptr = NULL;
|
|
for (value = strtok_r(buf, ",", &saveptr);
|
|
OB_SUCC(ret) && NULL != value;
|
|
value = strtok_r(NULL, ",", &saveptr)) {
|
|
int64_t index = -1;
|
|
ObString part_str(value);
|
|
if (OB_FAIL(ObTypeLibSysVar::find_type(part_str, index))) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
ObObj err_obj;
|
|
err_obj.set_varchar(part_str);
|
|
int log_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (log_ret = log_err_wrong_value_for_var(ret, err_obj))) {
|
|
// log_ret仅用于打日志,不覆盖ret
|
|
LOG_ERROR("fail to log error", K(ret), K(log_ret), K(err_obj));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSysVarUtils::log_bounds_error_or_warning(ObExecContext &ctx,
|
|
const ObSetVar &set_var,
|
|
const ObObj &in_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
// 为了兼容mysql,sql mode中含有STRICT_ALL_TABLES的时候报error,否则报warnning
|
|
const int64_t VALUE_STR_LENGTH = 32;
|
|
char val_str[VALUE_STR_LENGTH];
|
|
int64_t pos = 0;
|
|
if (OB_FAIL(in_val.print_plain_str_literal(val_str, VALUE_STR_LENGTH, pos))) {
|
|
LOG_WARN("fail to print varchar literal", K(ret));
|
|
} else {
|
|
ObSQLSessionInfo *session = ctx.get_my_session();
|
|
if (OB_ISNULL(session)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("session is NULL", K(ret));
|
|
} else if (session->get_sql_mode() & SMO_STRICT_ALL_TABLES) {
|
|
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
|
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR, set_var.var_name_.length(),
|
|
set_var.var_name_.ptr(), static_cast<int32_t>(strlen(val_str)), val_str);
|
|
} else {
|
|
LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, set_var.var_name_.length(),
|
|
set_var.var_name_.ptr(), static_cast<int32_t>(strlen(val_str)), val_str);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
}
|
|
}
|