Files
oceanbase/src/sql/engine/cmd/ob_set_names_executor.cpp
2023-01-28 15:43:48 +08:00

192 lines
9.6 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.
*/
#include "sql/engine/cmd/ob_set_names_executor.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/ob_exec_context.h"
#include "lib/string/ob_sql_string.h"
#include "share/inner_table/ob_inner_table_schema.h"
#include "observer/ob_server_struct.h"
using namespace oceanbase::sql;
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
int ObSetNamesExecutor::execute(ObExecContext &ctx, ObSetNamesStmt &stmt)
{
int ret = OB_SUCCESS;
ObSQLSessionInfo *session = NULL;
if (NULL == (session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "session is NULL", K(ret), K(ctx));
} else {
ObString charset;
if (stmt.is_default_charset()) {
// 和mysql兼容,取global的character_set_client值
if (OB_FAIL(get_global_sys_var_character_set_client(ctx, charset))) {
SQL_ENG_LOG(WARN, "fail to get global character_set_client", K(ret));
}
} else {
charset = stmt.get_charset();
}
if (OB_SUCC(ret)) {
ObString collation = stmt.get_collation();
ObCollationType collation_type = CS_TYPE_INVALID;
ObCharsetType cs_type = ObCharset::charset_type(charset);
if (CHARSET_INVALID == cs_type) {
ret = OB_ERR_UNKNOWN_CHARSET;
LOG_USER_ERROR(OB_ERR_UNKNOWN_CHARSET, charset.length(), charset.ptr());
} else {
charset = ObString::make_string(ObCharset::charset_name(cs_type));
if (stmt.is_default_collation() || !collation.empty()) {
collation_type = ObCharset::collation_type(collation);
if (CS_TYPE_INVALID == collation_type) {
ret = OB_ERR_UNKNOWN_COLLATION;
LOG_USER_ERROR(OB_ERR_UNKNOWN_COLLATION, collation.length(), collation.ptr());
} else if (!ObCharset::is_valid_collation(cs_type, collation_type)) {
ret = OB_ERR_COLLATION_MISMATCH;
LOG_USER_ERROR(OB_ERR_COLLATION_MISMATCH, collation.length(), collation.ptr(),
charset.length(), charset.ptr());
} else {
collation = ObString::make_string(ObCharset::collation_name(collation_type));
}
} else {
// the use default collation of this charset
collation_type = ObCharset::get_default_collation(cs_type);
collation = ObString::make_string(ObCharset::collation_name(collation_type));
}
}
if (OB_SUCC(ret)) {
if (!ObCharset::is_valid_connection_collation(collation_type)) {
ret = OB_NOT_SUPPORTED;
SQL_ENG_LOG(WARN, "collation type not supported",
"charset type", ObCharset::charset_name(cs_type),
"collation type", ObCharset::collation_name(collation_type));
}
}
if (OB_SUCC(ret)) {
if (stmt.is_set_names()) {
// SET NAMES
ObCollationType cs_coll_type = ObCharset::get_default_collation(ObCharset::charset_type(charset));
ObCollationType coll_type = ObCharset::collation_type(collation);
if (CS_TYPE_INVALID == cs_coll_type || CS_TYPE_INVALID == coll_type) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "cs coll type or coll type is invalid", K(ret), K(cs_coll_type), K(coll_type));
} else if (OB_FAIL(sql::ObSQLUtils::is_charset_data_version_valid(common::ObCharset::charset_type_by_coll(collation_type),
session->get_effective_tenant_id()))) {
SQL_EXE_LOG(WARN, "failed to check charset data version valid", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_CLIENT,
static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_RESULTS,
static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_CONNECTION,
static_cast<int64_t>(cs_coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_COLLATION_CONNECTION,
static_cast<int64_t>(coll_type)))) {
SQL_ENG_LOG(WARN, "failed to update sys var", K(ret));
}
} else {
// SET CHARACTER SET
ObObj database_charset;
ObObj database_collation;
ObCollationType cs_coll_type = ObCharset::get_default_collation(ObCharset::charset_type(charset));
if (OB_FAIL(sql::ObSQLUtils::is_charset_data_version_valid(common::ObCharset::charset_type_by_coll(cs_coll_type),
session->get_effective_tenant_id()))) {
SQL_EXE_LOG(WARN, "failed to check charset data version valid", K(ret));
} else if (OB_FAIL(session->get_sys_variable(SYS_VAR_CHARACTER_SET_DATABASE,
database_charset))) {
} else if (OB_FAIL(session->get_sys_variable(SYS_VAR_COLLATION_DATABASE,
database_collation))) {
} else {
ObCollationType collation_connection = static_cast<ObCollationType>(database_collation.get_int());
ObCharsetType charset_connection = ObCharset::charset_type_by_coll(collation_connection);
if (!ObCharset::is_valid_connection_collation(collation_connection)) {
ret = OB_NOT_SUPPORTED;
SQL_ENG_LOG(WARN, "connection collation type not supported",
"charset type", ObCharset::charset_name(charset_connection),
"collation type", ObCharset::collation_name(collation_connection));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_CLIENT,
static_cast<int64_t>(cs_coll_type)))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_RESULTS,
static_cast<int64_t>(cs_coll_type)))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_CHARACTER_SET_CONNECTION,
database_charset))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
} else if (OB_FAIL(session->update_sys_variable(SYS_VAR_COLLATION_CONNECTION,
database_collation))) {
SQL_EXE_LOG(WARN, "failed to update sys var", K(ret));
}
}
}
}
}
}
return ret;
}
int ObSetNamesExecutor::get_global_sys_var_character_set_client(
ObExecContext &ctx,
ObString &character_set_client) const
{
int ret = OB_SUCCESS;
ObSQLSessionInfo *session = NULL;
ObIAllocator &allocator = ctx.get_allocator();
ObSchemaGetterGuard schema_guard;
const ObSysVarSchema *var_schema = NULL;
ObObj value;
if (NULL == (session = ctx.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "session is NULL", K(ret), K(ctx));
} else if (OB_ISNULL(GCTX.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "schema service is null");
} else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(
session->get_effective_tenant_id(),
schema_guard))) {
SQL_ENG_LOG(WARN, "get schema guard failed", K(ret));
} else if (OB_FAIL(schema_guard.get_tenant_system_variable(session->get_effective_tenant_id(),
SYS_VAR_CHARACTER_SET_CLIENT, var_schema))) {
SQL_ENG_LOG(WARN, "get tenant system variable failed", K(ret));
} else if (OB_ISNULL(var_schema)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "var_schema is null");
} else if (OB_FAIL(var_schema->get_value(&allocator,
ObBasicSessionInfo::create_dtc_params(session),
value))) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "get value from var_schema failed", K(ret), K(*var_schema));
} else if (ObIntType != value.get_type()) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(ERROR, "sys var character_set_client's type must be ObIntType", K(ret), K(value));
} else {
ObCollationType coll_type = static_cast<ObCollationType>(value.get_int());
if (!ObCharset::is_valid_collation(coll_type)) {
ret = OB_ERR_UNEXPECTED;
SQL_ENG_LOG(WARN, "invalid collation type", K(ret), K(coll_type));
} else {
const char *cs_name_ptr = ObCharset::charset_name(coll_type);
character_set_client = ObString(cs_name_ptr);
}
}
return ret;
}