Files
oceanbase/src/sql/engine/expr/ob_expr_sys_context.cpp
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

881 lines
34 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 SQL_ENG
#include "sql/engine/expr/ob_expr_sys_context.h"
#include "sql/engine/expr/ob_expr_util.h"
#include "lib/ob_errno.h"
#include "lib/utility/ob_fast_convert.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/ob_exec_context.h"
#include "share/schema/ob_schema_struct.h"
#include "sql/engine/ob_exec_context.h"
#include "share/ob_global_context_operator.h"
using namespace oceanbase::share;
using namespace oceanbase::share::schema;
using namespace oceanbase::sql;
using namespace oceanbase::common;
namespace oceanbase
{
namespace sql
{
ObExprSysContext::ObExprSysContext(common::ObIAllocator &alloc)
: ObFuncExprOperator(alloc,
T_FUN_SYS_SYS_CONTEXT,
N_SYS_CONTEXT,
2 /*TWO_OR_THREE*/, NOT_ROW_DIMENSION)
{
}
ObExprSysContext::~ObExprSysContext() {}
int ObExprSysContext::calc_result_type2(ObExprResType& type,
ObExprResType& arg1,
ObExprResType& arg2,
common::ObExprTypeCtx& type_ctx) const
{
int ret = OB_SUCCESS;
const ObSQLSessionInfo *session = type_ctx.get_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
arg1.set_calc_type(ObVarcharType);
arg1.set_calc_collation_type(session->get_nls_collation());
arg2.set_calc_type(ObVarcharType);
arg2.set_calc_collation_type(session->get_nls_collation());
type.set_varchar();
type.set_collation_type(session->get_nls_collation());
type.set_collation_level(CS_LEVEL_SYSCONST);
const ObLengthSemantics def_ls = session->get_actual_nls_length_semantics();
type.set_length_semantics(def_ls);
// The data type of the return value is VARCHAR2.
// The default maximum size of the return value is 256 bytes.
// We can override this default by specifying the optional length parameter
// FIXME:But Now we don't support the third parameter which is the user specified length
type.set_length(DEFAULT_LENGTH);
}
return ret;
}
// define valid namespace parameter
// 3 types:
// userenv
// sys_session_roles //not supported
// user_define //not supported
const char namespace_paras[][10] =
{
"USERENV"
};
ObExprSysContext::UserEnvParameter ObExprSysContext::userenv_parameters_[] =
{
{"CURRENT_USERID", eval_curr_user_id},
{"CURRENT_USER", eval_curr_user},
{"SESSION_USERID", eval_schemaid},
{"SESSION_USER", eval_user},
{"CON_ID", eval_tenant_id},
{"CON_NAME", eval_tenant_name},
{"CURRENT_SCHEMA", eval_current_schema},
{"CURRENT_SCHEMAID", eval_current_schemaid},
{"SESSIONID", eval_sessionid},
{"IP_ADDRESS", eval_ip_address},
{"DB_NAME", eval_tenant_name},
{"SID", eval_sessionid},
{"INSTANCE", eval_instance},
{"INSTANCE_NAME", eval_instance_name},
{"LANG", eval_lang},
{"LANGUAGE", eval_language},
{"ACTION", eval_action},
{"CLIENT_INFO", eval_client_info},
{"MODULE", eval_module},
{"CLIENT_IDENTIFIER", eval_client_identifier},
};
ObExprSysContext::NLS_Lang ObExprSysContext::lang_map_[] =
{
{"AMERICAN", "US"},
};
int ObExprSysContext::get_userenv_fun(const ObString &pram_str, eval_fun &fun)
{
int ret = OB_SUCCESS;
fun = nullptr;
// userenv
bool found = false;
for (int64_t i = 0; !found && i < ARRAYSIZEOF(userenv_parameters_); ++i) {
if (0 == pram_str.case_compare(userenv_parameters_[i].name)) {
found = true;
fun = userenv_parameters_[i].eval;
}
}
if (!found) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(pram_str));
}
return ret;
}
int ObExprSysContext::get_eval_fun(const ObString& ns_str, const ObString& para_str,
eval_fun &fun)
{
int ret = OB_SUCCESS;
// userenv
if (0 == ns_str.case_compare(namespace_paras[0])) {
if (OB_FAIL(get_userenv_fun(para_str, fun))) {
LOG_WARN("fail to get userenv calc function", K(ret), K(ns_str));
}
} else {
// not supported, return null
fun = nullptr;
}
return ret;
}
int ObExprSysContext::eval_schemaid(const ObExpr &expr, ObDatum &res,
const ObDatum &arg1, const ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
uint64_t dbid = OB_INVALID_ID;
share::schema::ObSchemaGetterGuard schema_guard;
if (OB_FAIL(get_schema_guard(schema_guard, session->get_effective_tenant_id()))) {
LOG_WARN("failed to get schema guard", K(ret));
} else {
OZ(schema_guard.get_database_id(session->get_effective_tenant_id(),
session->get_user_name(), dbid));
char out_id[256];
sprintf(out_id, "%lu", dbid);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
}
}
return ret;
}
int ObExprSysContext::eval_curr_user_id(const ObExpr &expr, ObDatum &res,
const ObDatum &arg1, const ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
uint64_t curr_user_id = session->get_priv_user_id();
if (OB_INVALID_ID == curr_user_id) {
share::schema::ObSchemaGetterGuard schema_guard;
OZ (get_schema_guard(schema_guard, session->get_effective_tenant_id()));
OZ(schema_guard.get_database_id(session->get_effective_tenant_id(),
session->get_user_name(), curr_user_id));
}
if (OB_SUCC(ret)) {
char out_id[256];
sprintf(out_id, "%lu", curr_user_id);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
}
}
return ret;
}
int ObExprSysContext::eval_curr_user(const ObExpr &expr, ObDatum &res,
const ObDatum &arg1, const ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
share::schema::ObSchemaGetterGuard schema_guard;
if (OB_FAIL(get_schema_guard(schema_guard, session->get_effective_tenant_id()))) {
LOG_WARN("failed to get schema guard", K(ret));
} else {
// Only PL will call set_priv_user_id(), which won't change effective_tenant_id_;
// For the other scenarios, user_id_ is always correspond with effective_tenant_id_ even switch_tenant() is called.
const ObUserInfo *user_info = schema_guard.get_user_info(session->get_effective_tenant_id(),
session->get_priv_user_id());
if (OB_NOT_NULL(user_info)) {
const ObString &user_name = user_info->get_user_name_str();
ObString out_user_name;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(user_name, ObCharset::get_system_collation(),
out_user_name, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_user_name, out_user_name));
OX(res.set_string(out_user_name));
} else {
const ObString &user_name = session->get_user_name();
ObString out_user_name;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(user_name, ObCharset::get_system_collation(),
out_user_name, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_user_name, out_user_name));
OX(res.set_string(out_user_name));
}
}
}
return ret;
}
int ObExprSysContext::eval_current_schemaid(const ObExpr &expr, ObDatum &res,
const ObDatum &arg1, const ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
uint64_t dbid = session->get_database_id();
char out_id[256];
sprintf(out_id, "%lu", dbid);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
}
return ret;
}
int ObExprSysContext::eval_current_schema(const ObExpr &expr, ObDatum &res, const ObDatum &arg1,
const ObDatum &arg2, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
const ObString &db_name = session->get_database_name();
ObString out_db_name;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(db_name, ObCharset::get_system_collation(),
out_db_name, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_db_name, out_db_name));
OX(res.set_string(out_db_name));
}
return ret;
}
int ObExprSysContext::eval_user(const ObExpr &expr, ObDatum &res, const ObDatum &arg1,
const ObDatum &arg2, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
const ObString &user_name = session->get_user_name();
ObString out_user_name;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(user_name, ObCharset::get_system_collation(),
out_user_name, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_user_name, out_user_name));
OX(res.set_string(out_user_name));
}
return ret;
}
int ObExprSysContext::eval_tenant_name(const ObExpr &expr, ObDatum &res,
const ObDatum &arg1, const ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
const ObTenantSchema *tenant_schema = NULL;
share::schema::ObSchemaGetterGuard schema_guard;
OZ (get_schema_guard(schema_guard, session->get_effective_tenant_id()));
OZ(schema_guard.get_tenant_info(session->get_effective_tenant_id(), tenant_schema));
CK(OB_NOT_NULL(tenant_schema));
if (OB_SUCC(ret)) {
const ObString &user_name = tenant_schema->get_tenant_name_str();
ObString out_user_name;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(user_name, ObCharset::get_system_collation(),
out_user_name, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_user_name, out_user_name));
OX(res.set_string(out_user_name));
}
}
return ret;
}
int ObExprSysContext::eval_tenant_id(const ObExpr &expr, ObDatum &res, const ObDatum &arg1,
const ObDatum &arg2, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
uint64_t tenant_id = session->get_effective_tenant_id();
char out_id[256];
sprintf(out_id, "%lu", tenant_id);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
}
return ret;
}
int ObExprSysContext::eval_sessionid(const ObExpr &expr, ObDatum &res, const ObDatum &arg1,
const ObDatum &arg2, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
const uint64_t sid = session->get_sessid();
char out_id[256];
sprintf(out_id, "%lu", sid);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
}
return ret;
}
int ObExprSysContext::eval_ip_address(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1,
const common::ObDatum &arg2, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
const ObString &user_at_client_ip = session->get_user_at_client_ip();
int64_t start =0;
if (OB_FAIL(extract_ip(user_at_client_ip, start))) {
LOG_WARN("get real ip failed", K(ret));
} else {
ObString ip_address(user_at_client_ip.length() - start,
user_at_client_ip.length() - start,
const_cast<char *>(user_at_client_ip.ptr() + start));
ObString out_ip_address;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(ip_address, ObCharset::get_system_collation(),
out_ip_address, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_ip_address, out_ip_address));
OX(res.set_string(out_ip_address));
}
}
return ret;
}
int ObExprSysContext::eval_instance(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
uint64_t instance_id = GCTX.server_id_;
//OZ(uint_string(expr, ctx, instance_id, res));
char out_id[256];
sprintf(out_id, "%lu", instance_id);
ObString out_id_str(strlen(out_id), out_id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_id_str, ObCharset::get_system_collation(),
out_id_str, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_id_str, out_id_str));
OX(res.set_string(out_id_str));
return ret;
}
int ObExprSysContext::eval_instance_name(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObAddr &server_addr = GCTX.self_addr();
char ip_port_str[MAX_IP_PORT_LENGTH];
if (OB_FAIL(server_addr.ip_port_to_string(ip_port_str, sizeof(ip_port_str)))) {
LOG_WARN("fail to generate ip_port_str", K(ret), K(server_addr));
} else {
ObString out_instance(strlen(ip_port_str), ip_port_str);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_instance, ObCharset::get_system_collation(),
out_instance, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_instance, out_instance));
OX(res.set_string(out_instance));
}
return ret;
}
int ObExprSysContext::eval_language(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
ObObj language;
ObObj territory;
ObObj characterset;
//return language_territory.characterset
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
if (OB_FAIL(session->get_sys_variable(SYS_VAR_NLS_LANGUAGE, language))) {
LOG_WARN("failed to get sys var", K(ret));
} else if (OB_FAIL(session->get_sys_variable(SYS_VAR_NLS_TERRITORY, territory))) {
LOG_WARN("failed to get sys var", K(ret));
} else if (OB_FAIL(session->get_sys_variable(SYS_VAR_NLS_CHARACTERSET, characterset))) {
LOG_WARN("failed to get sys var", K(ret));
} else {
const int64_t MAX_LANGUAGE_LEN = 256;
char language_str[MAX_LANGUAGE_LEN];
int64_t pos = 0;
if (OB_UNLIKELY(MAX_LANGUAGE_LEN < language.get_string().length()
+ territory.get_string().length()
+ characterset.get_string().length() + 2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("language str is not enough", K(ret));
} else {
MEMCPY(language_str, language.get_string().ptr(), language.get_string().length());
pos += language.get_string().length();
language_str[pos++] = '_';
MEMCPY(language_str + pos, territory.get_string().ptr(), territory.get_string().length());
pos += territory.get_string().length();
language_str[pos++] = '.';
MEMCPY(language_str + pos, characterset.get_string().ptr(),
characterset.get_string().length());
pos += characterset.get_string().length();
ObString out_language(pos, language_str);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(out_language, ObCharset::get_system_collation(),
out_language, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_language, out_language));
OX(res.set_string(out_language));
}
}
}
return ret;
}
int ObExprSysContext::eval_lang(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
ObObj language;
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
if (OB_FAIL(session->get_sys_variable(SYS_VAR_NLS_LANGUAGE, language))) {
LOG_WARN("failed to get sys var", K(ret));
} else {
bool found = false;
ObString abbreviated;
for (int64_t i = 0; !found && i < ARRAYSIZEOF(lang_map_); ++i) {
if (0 == language.get_string().case_compare(lang_map_[i].language)) {
found = true;
abbreviated.assign(lang_map_[i].abbreviated, strlen(lang_map_[i].abbreviated));
}
}
if (!found) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(language));
} else {
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(abbreviated, ObCharset::get_system_collation(),
abbreviated, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, abbreviated, abbreviated));
OX(res.set_string(abbreviated));
}
}
}
return ret;
}
int ObExprSysContext::eval_action(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
ObString action;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(session->get_action_name(),
ObCharset::get_system_collation(),
action, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, action, action));
OX(res.set_string(action));
}
return ret;
}
int ObExprSysContext::eval_client_info(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
ObString client_info;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(session->get_client_info(),
ObCharset::get_system_collation(),
client_info, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, client_info, client_info));
OX(res.set_string(client_info));
}
return ret;
}
int ObExprSysContext::eval_module(const ObExpr &expr, common::ObDatum &res,
const common::ObDatum &arg1, const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
ObString module;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(session->get_module_name(),
ObCharset::get_system_collation(),
module, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, module, module));
OX(res.set_string(module));
}
return ret;
}
int ObExprSysContext::eval_client_identifier(const ObExpr &expr,
common::ObDatum &res,
const common::ObDatum &arg1,
const common::ObDatum &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
UNUSED(arg1);
UNUSED(arg2);
const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret)) {
if (session->get_client_identifier().length() > 0) {
ObString client_id;
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(session->get_client_identifier(),
ObCharset::get_system_collation(),
client_id, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, client_id, client_id));
OX(res.set_string(client_id));
} else {
res.set_null();
}
}
return ret;
}
int ObExprSysContext::eval_application_context(const ObExpr &expr, ObDatum &res,
const ObString &arg1, const ObString &arg2,
ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
ObString value;
ObString out_value;
ObSQLSessionInfo *session = nullptr;
bool exist = false;
ObISQLClient *sql_client = nullptr;
if (arg1.length() > OB_MAX_CONTEXT_STRING_LENGTH) {
ret = OB_ERR_INVALID_INPUT_ARGUMENT;
LOG_USER_ERROR(OB_ERR_INVALID_INPUT_ARGUMENT, 1/*param_idx*/);
} else if (arg2.length() > OB_MAX_CONTEXT_STRING_LENGTH) {
ret = OB_ERR_INVALID_INPUT_ARGUMENT;
LOG_USER_ERROR(OB_ERR_INVALID_INPUT_ARGUMENT, 2/*param_idx*/);
} else if (OB_ISNULL(session = ctx.exec_ctx_.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (OB_FAIL(session->get_context_values(arg1, arg2, value, exist))) {
LOG_WARN("failed to get context from session", K(ret));
} else if (!exist) {
ObGlobalContextOperator ctx_operator;
share::schema::ObSchemaGetterGuard schema_guard;
if (OB_FAIL(get_schema_guard(schema_guard, session->get_effective_tenant_id()))) {
LOG_WARN("failed to get schema guard", K(ret));
} else {
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
const ObString &username = session->get_user_name();
const ObString &client_id = session->get_client_identifier();
const ObContextSchema *ctx_schema = nullptr;
if (OB_FAIL(schema_guard.get_context_schema_with_name(session->get_effective_tenant_id(),
arg1, ctx_schema))) {
LOG_WARN("failed to get context schema", K(ret));
} else if (OB_ISNULL(ctx_schema)) {
// not exist, do nothing and return null
} else if (OB_ISNULL(sql_client = ctx.exec_ctx_.get_sql_proxy())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get sql proxy", K(ret));
} else if (OB_FAIL(ctx_operator.read_global_context(ctx_schema->get_tenant_id(),
ctx_schema->get_context_id(),
arg2,
client_id,
username,
value,
exist,
*sql_client,
calc_alloc))) {
LOG_WARN("failed to read global context value", K(ret));
} else if (exist) {
ObExprStrResAlloc res_alloc(expr, ctx);
OZ(ObExprUtil::convert_string_collation(value,
ObCharset::get_system_collation(),
out_value, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_value, out_value));
}
}
} else {
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
OZ(ObExprUtil::convert_string_collation(value,
ObCharset::get_system_collation(),
out_value, expr.datum_meta_.cs_type_,
calc_alloc));
OZ(deep_copy_ob_string(res_alloc, out_value, out_value));
}
if (OB_SUCC(ret)) {
if (exist) {
OX(res.set_string(out_value));
} else {
res.set_null();
}
}
return ret;
}
int ObExprSysContext::eval_sys_context(const ObExpr &expr, ObEvalCtx &ctx,
ObDatum &res)
{
int ret = OB_SUCCESS;
ObDatum *ns = NULL;
ObDatum *para = NULL;
eval_fun fun = NULL;
if (OB_FAIL(expr.eval_param_value(ctx, ns, para))) {
LOG_WARN("eval arg failed", K(ret));
} else if (ns->is_null() || para->is_null()) {
res.set_null();
} else {
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
ObString ns_str;
ObString para_str;
ObCollationType ns_coll = expr.args_[0]->datum_meta_.cs_type_;
ObCollationType para_coll = expr.args_[1]->datum_meta_.cs_type_;
ObCollationType sys_coll = ObCharset::get_system_collation();
OZ(ob_write_string(calc_alloc, ns->get_string(), ns_str));
OZ(ob_write_string(calc_alloc, para->get_string(), para_str));
OZ(ObExprUtil::convert_string_collation(ns_str, ns_coll, ns_str,
sys_coll, calc_alloc));
OZ(ObExprUtil::convert_string_collation(para_str, para_coll, para_str,
sys_coll, calc_alloc));
OZ(get_eval_fun(ns_str, para_str, fun));
if (OB_SUCC(ret)) {
if (NULL == fun) {
if (ns->is_null() || para->is_null()) {
res.set_null();
} else {
ObCharset::caseup(sys_coll, ns_str);
ObCharset::caseup(sys_coll, para_str);
if (OB_FAIL(eval_application_context(expr, res, ns_str, para_str, ctx))) {
LOG_WARN("failed to eval application context", K(ret));
}
}
} else if (OB_FAIL(fun(expr, res, *ns, *para, ctx))) {
LOG_WARN("fail to calc result", K(ret));
}
}
}
return ret;
}
int ObExprSysContext::cg_expr(ObExprCGCtx &ctx, const ObRawExpr &raw_expr,
ObExpr &rt_expr) const
{
int ret = OB_SUCCESS;
UNUSED(ctx);
UNUSED(raw_expr);
CK(2 == rt_expr.arg_cnt_);
OX(rt_expr.eval_func_ = eval_sys_context);
return ret;
}
int ObExprSysContext::uint_string(const ObExpr &expr, ObEvalCtx &ctx,
uint64_t id, ObDatum &res)
{
int ret = OB_SUCCESS;
ObFastFormatInt ffi(id);
ObExprStrResAlloc res_alloc(expr, ctx);
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
ObIAllocator &calc_alloc = alloc_guard.get_allocator();
ObString id_str_utf8(ffi.length(), ffi.ptr());
ObString id_str;
OZ(ObExprUtil::convert_string_collation(id_str_utf8, ObCharset::get_system_collation(),
id_str, expr.datum_meta_.cs_type_, calc_alloc));
OZ(deep_copy_ob_string(res_alloc, id_str, id_str));
OX(res.set_string(id_str));
return ret;
}
int ObExprSysContext::extract_ip(const ObString &user_at_client_ip, int64_t &start)
{
int ret = OB_SUCCESS;
start = 0;
if (user_at_client_ip.length() <= 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("wrong length of ip address param", K(ret));
} else {
bool end_loop = false;
for (; !end_loop && start < user_at_client_ip.length(); ++start) {
if ('@' == user_at_client_ip[start]) {
end_loop = true;
}
}
}
return ret;
}
int ObExprSysContext::get_schema_guard(share::schema::ObSchemaGetterGuard &schema_guard, uint64_t tenant_id)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(GCTX.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get schema_service", K(ret));
} else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) {
LOG_WARN("failed to get schema guard", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase