881 lines
34 KiB
C++
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
|