support set names/charset and variables in one sql

This commit is contained in:
st0
2021-11-09 10:48:59 +08:00
committed by LINxiansheng
parent fa9b5fdfc0
commit 878c594b56
31 changed files with 21749 additions and 21858 deletions

View File

@ -39,7 +39,7 @@ using namespace common;
using namespace share;
using namespace share::schema;
namespace sql {
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableSetNode>& sys_var_nodes,
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& sys_var_nodes,
share::schema::ObTenantSchema& tenant_schema, common::ObIArray<obrpc::ObSysVarIdValue>& sys_var_list);
int ObCreateTenantExecutor::execute(ObExecContext& ctx, ObCreateTenantStmt& stmt)
@ -111,7 +111,7 @@ int ObCreateTenantExecutor::execute(ObExecContext& ctx, ObCreateTenantStmt& stmt
return ret;
}
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableSetNode>& sys_var_nodes,
int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& sys_var_nodes,
share::schema::ObTenantSchema& tenant_schema, common::ObIArray<obrpc::ObSysVarIdValue>& sys_var_list)
{
int ret = OB_SUCCESS;
@ -141,104 +141,110 @@ int check_sys_var_options(ObExecContext& ctx, const common::ObIArray<ObVariableS
plan_ctx->has_cur_time() ? plan_ctx->get_cur_time().get_timestamp() : ObTimeUtility::current_time();
phy_plan_ctx.set_cur_time(cur_time, *session);
ObVariableSetStmt::VariableSetNode tmp_node; // just for init node
ObVariableSetStmt::VariableNamesSetNode tmp_node; // just for init node
for (int64_t i = 0; OB_SUCC(ret) && i < sys_var_nodes.count(); ++i) {
ObVariableSetStmt::VariableSetNode& cur_node = tmp_node;
ObVariableSetStmt::VariableNamesSetNode& var_names_node = tmp_node;
ObBasicSysVar* sys_var = NULL;
if (OB_FAIL(sys_var_nodes.at(i, cur_node))) {
if (OB_FAIL(sys_var_nodes.at(i, var_names_node))) {
LOG_WARN("failed to access node from array", K(ret));
} else if (!cur_node.is_system_variable_) {
} else if (OB_UNLIKELY(!var_names_node.is_set_variable_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("create tenant can only set system variables", K(cur_node), K(ret));
} else if (OB_FAIL(session->get_sys_variable_by_name(cur_node.variable_name_, sys_var))) {
LOG_WARN("fail to get_sys_variable_by_name", K(ret));
} else if (OB_ISNULL(sys_var)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got sys var is NULL", K(ret));
} else if (cur_node.is_set_default_) { // set default, then do nothing
LOG_WARN("only expect set variables here", K(ret), K(var_names_node));
} else {
ObObj value_obj;
// first:calculate value of expression
ObNewRow tmp_row;
RowDesc row_desc;
ObExprGeneratorImpl expr_gen(0, 0, NULL, row_desc);
ObSqlExpression sql_expr(ctx.get_allocator(), 0);
if (OB_ISNULL(cur_node.value_expr_)) {
ObVariableSetStmt::VariableSetNode& cur_node = var_names_node.var_set_node_;
if (!cur_node.is_system_variable_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node.value_expr_ is NULL", K(ret));
LOG_WARN("create tenant can only set system variables", K(cur_node), K(ret));
} else if (OB_FAIL(session->get_sys_variable_by_name(cur_node.variable_name_, sys_var))) {
LOG_WARN("fail to get_sys_variable_by_name", K(ret));
} else if (OB_ISNULL(sys_var)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got sys var is NULL", K(ret));
} else if (cur_node.is_set_default_) { // set default, then do nothing
} else {
if (!is_strict_mode(session->get_sql_mode())) {
expr_ctx.cast_mode_ = CM_WARN_ON_FAIL;
}
if (OB_FAIL(expr_gen.generate(*cur_node.value_expr_, sql_expr))) {
LOG_WARN("fail to fill sql expression", K(ret));
} else if (FALSE_IT(phy_plan.set_regexp_op_count(expr_gen.get_cur_regexp_op_count()))) {
} else if (FALSE_IT(phy_plan.set_like_op_count(expr_gen.get_cur_like_op_count()))) {
} else if (OB_FAIL(sql_expr.calc(expr_ctx, tmp_row, value_obj))) {
LOG_WARN("fail to calc value", K(*cur_node.value_expr_), K(ret));
} else { /*do nothing*/
}
}
// second:convert value to dest type
uint64_t fake_tenant_id = OB_INVALID_ID;
ObSetVar set_var(cur_node.variable_name_,
cur_node.set_scope_,
cur_node.is_set_default_,
fake_tenant_id,
*expr_ctx.calc_buf_,
*sql_proxy);
if (OB_SUCC(ret)) {
ObObj out_obj;
const bool is_set_stmt = false;
if (OB_FAIL(ObVariableSetExecutor::check_and_convert_sys_var(
ctx, set_var, *sys_var, value_obj, out_obj, is_set_stmt))) {
LOG_WARN("fail to check_and_convert_sys_var", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else if (OB_FAIL(ObVariableSetExecutor::cast_value(
ctx, cur_node, fake_tenant_id, *expr_ctx.calc_buf_, *sys_var, value_obj, out_obj))) {
LOG_WARN("fail to cast value", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else { /*do nothing*/
}
}
// add variable value into ObCreateTenantArg
if (OB_SUCC(ret)) {
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 || 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) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("collation or charset can not be modify temporarily", K(set_var), K(ret));
ObObj value_obj;
// first:calculate value of expression
ObNewRow tmp_row;
RowDesc row_desc;
ObExprGeneratorImpl expr_gen(0, 0, NULL, row_desc);
ObSqlExpression sql_expr(ctx.get_allocator(), 0);
if (OB_ISNULL(cur_node.value_expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node.value_expr_ is NULL", K(ret));
} else {
// read only should also modify tenant_schema
if (set_var.var_name_ == OB_SV_READ_ONLY) {
if (session->get_in_transaction()) {
ret = OB_ERR_LOCK_OR_ACTIVE_TRANSACTION;
LOG_WARN("Can't execute the given command because "
"you have active locked tables or an active transaction",
K(ret));
} else {
tenant_schema.set_read_only(value_obj.get_bool());
}
if (!is_strict_mode(session->get_sql_mode())) {
expr_ctx.cast_mode_ = CM_WARN_ON_FAIL;
}
ObSysVarClassType sys_id = sys_var->get_type();
ObString val_str;
expr_ctx.calc_buf_ = &ctx.get_allocator(); // make sure use this allocator to keep ObString is valid
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
EXPR_GET_VARCHAR_V2(value_obj, val_str);
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(val_str.length() > OB_MAX_SYS_VAR_VAL_LENGTH)) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("set sysvar value is overflow",
"max length",
OB_MAX_SYS_VAR_VAL_LENGTH,
"value length",
val_str.length(),
K(sys_id),
K(val_str));
} else if (OB_FAIL(sys_var_list.push_back(obrpc::ObSysVarIdValue(sys_id, val_str)))) {
LOG_WARN("failed to push back", K(sys_id), K(val_str), K(ret));
if (OB_FAIL(expr_gen.generate(*cur_node.value_expr_, sql_expr))) {
LOG_WARN("fail to fill sql expression", K(ret));
} else if (FALSE_IT(phy_plan.set_regexp_op_count(expr_gen.get_cur_regexp_op_count()))) {
} else if (FALSE_IT(phy_plan.set_like_op_count(expr_gen.get_cur_like_op_count()))) {
} else if (OB_FAIL(sql_expr.calc(expr_ctx, tmp_row, value_obj))) {
LOG_WARN("fail to calc value", K(*cur_node.value_expr_), K(ret));
} else { /*do nothing*/
}
}
// second:convert value to dest type
uint64_t fake_tenant_id = OB_INVALID_ID;
ObSetVar set_var(cur_node.variable_name_,
cur_node.set_scope_,
cur_node.is_set_default_,
fake_tenant_id,
*expr_ctx.calc_buf_,
*sql_proxy);
if (OB_SUCC(ret)) {
ObObj out_obj;
const bool is_set_stmt = false;
if (OB_FAIL(ObVariableSetExecutor::check_and_convert_sys_var(
ctx, set_var, *sys_var, value_obj, out_obj, is_set_stmt))) {
LOG_WARN("fail to check_and_convert_sys_var", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else if (OB_FAIL(ObVariableSetExecutor::cast_value(
ctx, cur_node, fake_tenant_id, *expr_ctx.calc_buf_, *sys_var, value_obj, out_obj))) {
LOG_WARN("fail to cast value", K(cur_node), K(*sys_var), K(value_obj), K(ret));
} else if (FALSE_IT(value_obj = out_obj)) {
} else { /*do nothing*/
}
}
// add variable value into ObCreateTenantArg
if (OB_SUCC(ret)) {
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 || 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) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("collation or charset can not be modify temporarily", K(set_var), K(ret));
} else {
// read only should also modify tenant_schema
if (set_var.var_name_ == OB_SV_READ_ONLY) {
if (session->get_in_transaction()) {
ret = OB_ERR_LOCK_OR_ACTIVE_TRANSACTION;
LOG_WARN("Can't execute the given command because "
"you have active locked tables or an active transaction",
K(ret));
} else {
tenant_schema.set_read_only(value_obj.get_bool());
}
}
ObSysVarClassType sys_id = sys_var->get_type();
ObString val_str;
expr_ctx.calc_buf_ = &ctx.get_allocator(); // make sure use this allocator to keep ObString is valid
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
EXPR_GET_VARCHAR_V2(value_obj, val_str);
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(val_str.length() > OB_MAX_SYS_VAR_VAL_LENGTH)) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("set sysvar value is overflow",
"max length",
OB_MAX_SYS_VAR_VAL_LENGTH,
"value length",
val_str.length(),
K(sys_id),
K(val_str));
} else if (OB_FAIL(sys_var_list.push_back(obrpc::ObSysVarIdValue(sys_id, val_str)))) {
LOG_WARN("failed to push back", K(sys_id), K(val_str), K(ret));
}
}
}
}