support set names/charset and variables in one sql
This commit is contained in:
@ -3570,7 +3570,8 @@ int ObAlterSystemSetResolver::resolve(const ParseNode& parse_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(var_node))) {
|
||||
if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(
|
||||
ObVariableSetStmt::make_variable_name_node(var_node)))) {
|
||||
LOG_WARN("Add set entry failed", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* 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/resolver/cmd/ob_set_names_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_set_names_stmt.h"
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace oceanbase::common;
|
||||
namespace sql {
|
||||
ObSetNamesResolver::ObSetNamesResolver(ObResolverParams& params) : ObCMDResolver(params)
|
||||
{}
|
||||
|
||||
ObSetNamesResolver::~ObSetNamesResolver()
|
||||
{}
|
||||
|
||||
int ObSetNamesResolver::resolve(const ParseNode& parse_tree)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (T_SET_NAMES != parse_tree.type_ && T_SET_CHARSET != parse_tree.type_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
SQL_RESV_LOG(WARN, "create stmt failed", K(ret));
|
||||
} else if (OB_ISNULL(parse_tree.children_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_RESV_LOG(WARN, "parse_tree.children_ is null.", K(ret));
|
||||
} else if (OB_ISNULL(parse_tree.children_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_RESV_LOG(WARN, "parse_tree.children_[0] is null.", K(ret));
|
||||
} else {
|
||||
ObSetNamesStmt* stmt = NULL;
|
||||
if (OB_ISNULL(stmt = create_stmt<ObSetNamesStmt>())) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
SQL_RESV_LOG(ERROR, "create stmt failed", K(ret));
|
||||
} else {
|
||||
if (T_SET_NAMES == parse_tree.type_) {
|
||||
// SET NAMES
|
||||
stmt->set_is_set_names(true);
|
||||
if (T_DEFAULT == parse_tree.children_[0]->type_) {
|
||||
stmt->set_is_default_charset(true);
|
||||
} else {
|
||||
ObString charset;
|
||||
charset.assign_ptr(
|
||||
parse_tree.children_[0]->str_value_, static_cast<int32_t>(parse_tree.children_[0]->str_len_));
|
||||
if (0 == charset.case_compare("utf16")) {
|
||||
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
||||
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
|
||||
static_cast<int>(strlen("character_set_client")),
|
||||
"character_set_client",
|
||||
charset.length(),
|
||||
charset.ptr());
|
||||
} else {
|
||||
stmt->set_charset(charset);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (NULL == parse_tree.children_[1]) {
|
||||
// do nothing
|
||||
} else if (T_DEFAULT == parse_tree.children_[1]->type_) {
|
||||
stmt->set_is_default_collation(true);
|
||||
} else {
|
||||
ObString collation;
|
||||
collation.assign_ptr(
|
||||
parse_tree.children_[1]->str_value_, static_cast<int32_t>(parse_tree.children_[1]->str_len_));
|
||||
stmt->set_collation(collation);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// SET CHARACTER SET
|
||||
stmt->set_is_set_names(false);
|
||||
if (T_DEFAULT == parse_tree.children_[0]->type_) {
|
||||
stmt->set_is_default_charset(true);
|
||||
} else {
|
||||
ObString charset;
|
||||
charset.assign_ptr(
|
||||
parse_tree.children_[0]->str_value_, static_cast<int32_t>(parse_tree.children_[0]->str_len_));
|
||||
stmt->set_charset(charset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _OB_SET_NAMES_RESOLVER_H
|
||||
#define _OB_SET_NAMES_RESOLVER_H
|
||||
#include "sql/resolver/cmd/ob_cmd_resolver.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
// resolver for both SET NAMES and SET CHARSET
|
||||
class ObSetNamesResolver : public ObCMDResolver {
|
||||
public:
|
||||
explicit ObSetNamesResolver(ObResolverParams& params);
|
||||
virtual ~ObSetNamesResolver();
|
||||
|
||||
virtual int resolve(const ParseNode& parse_tree);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObSetNamesResolver);
|
||||
};
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
#endif // _OB_SET_NAMES_RESOLVER_H
|
||||
@ -1,94 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _OB_SET_NAMES_STMT_H
|
||||
#define _OB_SET_NAMES_STMT_H
|
||||
#include "lib/string/ob_string.h"
|
||||
#include "sql/resolver/cmd/ob_cmd_stmt.h"
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
// statement for both SET NAMES and SET CHARSET
|
||||
class ObSetNamesStmt : public ObCMDStmt {
|
||||
public:
|
||||
ObSetNamesStmt()
|
||||
: ObCMDStmt(stmt::T_SET_NAMES), is_set_names_(true), is_default_charset_(false), is_default_collation_(false)
|
||||
{}
|
||||
virtual ~ObSetNamesStmt()
|
||||
{}
|
||||
|
||||
bool is_set_names() const
|
||||
{
|
||||
return this->is_set_names_;
|
||||
}
|
||||
void set_is_set_names(bool is_set_names)
|
||||
{
|
||||
this->is_set_names_ = is_set_names;
|
||||
}
|
||||
|
||||
bool is_default_charset() const
|
||||
{
|
||||
return is_default_charset_;
|
||||
}
|
||||
void set_is_default_charset(bool is_default)
|
||||
{
|
||||
is_default_charset_ = is_default;
|
||||
}
|
||||
|
||||
bool is_default_collation() const
|
||||
{
|
||||
return is_default_collation_;
|
||||
}
|
||||
void set_is_default_collation(bool is_default)
|
||||
{
|
||||
is_default_collation_ = is_default;
|
||||
}
|
||||
|
||||
const common::ObString& get_charset() const
|
||||
{
|
||||
return this->charset_;
|
||||
}
|
||||
void set_charset(const common::ObString& charset)
|
||||
{
|
||||
this->charset_ = charset;
|
||||
}
|
||||
|
||||
const common::ObString& get_collation() const
|
||||
{
|
||||
return this->collation_;
|
||||
}
|
||||
void set_collation(const common::ObString& collation)
|
||||
{
|
||||
this->collation_ = collation;
|
||||
}
|
||||
TO_STRING_KV(N_STMT_TYPE, ((int)stmt_type_), K_(is_set_names), K_(is_default_charset), K_(is_default_collation),
|
||||
K_(charset), K_(collation));
|
||||
|
||||
private:
|
||||
// types and constants
|
||||
private:
|
||||
// function members
|
||||
private:
|
||||
// data members
|
||||
bool is_set_names_; // SET NAMES or SET CHARSET?
|
||||
bool is_default_charset_;
|
||||
bool is_default_collation_;
|
||||
common::ObString charset_;
|
||||
common::ObString collation_;
|
||||
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObSetNamesStmt);
|
||||
};
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
#endif // _OB_SET_NAMES_STMT_H
|
||||
@ -91,17 +91,18 @@ int ObSetTransactionResolver::resolve(const ParseNode& parse_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && set_isolation_level) {
|
||||
if (OB_FAIL(build_isolation_expr(isolation_var_node.value_expr_, isolation_level))) {
|
||||
LOG_WARN("fail to build isolation expr", K(ret));
|
||||
} else if (OB_FAIL(stmt->add_variable_node(isolation_var_node))) {
|
||||
} else if (OB_FAIL(stmt->add_variable_node(ObVariableSetStmt::make_variable_name_node(isolation_var_node)))) {
|
||||
LOG_WARN("fail to add variable node", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && set_access_mode) {
|
||||
if (OB_FAIL(build_access_expr(access_var_node.value_expr_, is_read_only))) {
|
||||
LOG_WARN("fail to build access expr", K(ret));
|
||||
} else if (OB_FAIL(stmt->add_variable_node(access_var_node))) {
|
||||
} else if (OB_FAIL(stmt->add_variable_node(ObVariableSetStmt::make_variable_name_node(access_var_node)))) {
|
||||
LOG_WARN("fail to add variable node", K(ret));
|
||||
} else {
|
||||
LOG_DEBUG("add variable node", K(is_read_only));
|
||||
|
||||
@ -46,124 +46,27 @@ int ObVariableSetResolver::resolve(const ParseNode& parse_tree)
|
||||
variable_set_stmt->set_actual_tenant_id(session_info_->get_effective_tenant_id());
|
||||
ParseNode* set_node = NULL;
|
||||
ObVariableSetStmt::VariableSetNode var_node;
|
||||
ObVariableSetStmt::NamesSetNode names_node;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < parse_tree.num_child_; ++i) {
|
||||
if (OB_ISNULL(set_node = parse_tree.children_[i])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("set node is NULL", K(ret));
|
||||
} else if (OB_UNLIKELY(T_VAR_VAL != set_node->type_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("set_node->type_ must be T_VAR_VAL", K(ret), K(set_node->type_));
|
||||
} else {
|
||||
ParseNode* var = NULL;
|
||||
switch (set_node->value_) {
|
||||
case 0:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_SESSION;
|
||||
break;
|
||||
case 1:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_GLOBAL;
|
||||
variable_set_stmt->set_has_global_variable(true);
|
||||
break;
|
||||
case 2:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_SESSION;
|
||||
break;
|
||||
default:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_NEXT_TRANS;
|
||||
break;
|
||||
} else if (T_VAR_VAL == set_node->type_) {
|
||||
if (OB_FAIL(resolve_set_variable(*set_node, var_node, variable_set_stmt))) {
|
||||
LOG_WARN("resolve set variable failed", K(ret));
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(var = set_node->children_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("var is NULL", K(ret));
|
||||
} else {
|
||||
ObString var_name;
|
||||
if (T_IDENT == var->type_) {
|
||||
var_node.is_system_variable_ = true;
|
||||
var_name.assign_ptr(var->str_value_, static_cast<int32_t>(var->str_len_));
|
||||
} else if (T_OBJ_ACCESS_REF == var->type_) { // Oracle mode
|
||||
const ParseNode* name_node = NULL;
|
||||
if (OB_ISNULL(name_node = var->children_[0]) || OB_UNLIKELY(var->children_[1] != NULL)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name not an identifier type");
|
||||
} else if (OB_UNLIKELY(name_node->type_ != T_IDENT)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name not an identifier type");
|
||||
} else {
|
||||
var_node.is_system_variable_ = true;
|
||||
var_name.assign_ptr(name_node->str_value_, static_cast<int32_t>(name_node->str_len_));
|
||||
}
|
||||
} else {
|
||||
var_node.is_system_variable_ = (T_SYSTEM_VARIABLE == var->type_);
|
||||
var_name.assign_ptr(var->str_value_, static_cast<int32_t>(var->str_len_));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ob_write_string(*allocator_, var_name, var_node.variable_name_))) {
|
||||
LOG_WARN("Can not malloc space for variable name", K(ret));
|
||||
} else {
|
||||
ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, var_node.variable_name_);
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(set_node->children_[1])) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("value node is NULL", K(ret));
|
||||
} else if (T_DEFAULT == set_node->children_[1]->type_) {
|
||||
// set system_variable = default
|
||||
var_node.is_set_default_ = true;
|
||||
} else if (var_node.is_system_variable_) {
|
||||
ParseNode value_node;
|
||||
if (T_IDENT == set_node->children_[1]->type_) {
|
||||
MEMCPY(&value_node, set_node->children_[1], sizeof(ParseNode));
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else if (T_COLUMN_REF == set_node->children_[1]->type_) {
|
||||
if (NULL == set_node->children_[1]->children_[0] && NULL == set_node->children_[1]->children_[1] &&
|
||||
NULL != set_node->children_[1]->children_[2]) {
|
||||
MEMCPY(&value_node, set_node->children_[1]->children_[2], sizeof(ParseNode));
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node->children_[1], sizeof(ParseNode));
|
||||
}
|
||||
} else if (T_OBJ_ACCESS_REF == set_node->children_[1]->type_) { // Oracle mode
|
||||
if (OB_ISNULL(set_node->children_[1]->children_[0]) ||
|
||||
OB_UNLIKELY(set_node->children_[1]->children_[1] != NULL)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable value not a varchar nor identifier type");
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node->children_[1]->children_[0], sizeof(ParseNode));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (T_IDENT == set_node->children_[1]->children_[0]->type_) {
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else if (T_FUN_SYS == set_node->children_[1]->children_[0]->type_) {
|
||||
// do nothing
|
||||
} else {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable value type");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node->children_[1], sizeof(ParseNode));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == var_node.variable_name_.case_compare("ob_compatibility_mode") &&
|
||||
0 == strncasecmp(
|
||||
value_node.str_value_, "oracle", std::min(static_cast<int32_t>(value_node.str_len_), 6))) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Not support oracle mode");
|
||||
} else if (OB_FAIL(
|
||||
ObResolverUtils::resolve_const_expr(params_, value_node, var_node.value_expr_, NULL))) {
|
||||
LOG_WARN("resolve variable value failed", K(ret));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(ObResolverUtils::resolve_const_expr(
|
||||
params_, *set_node->children_[1], var_node.value_expr_, NULL))) {
|
||||
LOG_WARN("resolve variable value failed", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(var_node))) {
|
||||
LOG_WARN("Add set entry failed", K(ret));
|
||||
}
|
||||
} else if (T_SET_NAMES == set_node->type_ || T_SET_CHARSET == set_node->type_) {
|
||||
if (OB_FAIL(resolve_set_names(*set_node, names_node)))
|
||||
LOG_WARN("resolve set names failed", K(ret));
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("unexpected set_node->type_ ", K(ret), K(set_node->type_));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
const bool is_set_variable = T_VAR_VAL == set_node->type_;
|
||||
ObVariableSetStmt::VariableNamesSetNode var_names_node(is_set_variable, var_node, names_node);
|
||||
if (OB_FAIL(variable_set_stmt->add_variable_node(var_names_node))) {
|
||||
LOG_WARN("Add set entry failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,6 +74,183 @@ int ObVariableSetResolver::resolve(const ParseNode& parse_tree)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObVariableSetResolver::resolve_set_variable(const ParseNode &set_node,
|
||||
ObVariableSetStmt::VariableSetNode &var_node,
|
||||
ObVariableSetStmt* variable_set_stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ParseNode* var = NULL;
|
||||
switch (set_node.value_) {
|
||||
case 0:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_SESSION;
|
||||
break;
|
||||
case 1:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_GLOBAL;
|
||||
variable_set_stmt->set_has_global_variable(true);
|
||||
break;
|
||||
case 2:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_SESSION;
|
||||
break;
|
||||
default:
|
||||
var_node.set_scope_ = ObSetVar::SET_SCOPE_NEXT_TRANS;
|
||||
break;
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(var = set_node.children_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("var is NULL", K(ret));
|
||||
} else {
|
||||
ObString var_name;
|
||||
if (T_IDENT == var->type_) {
|
||||
var_node.is_system_variable_ = true;
|
||||
var_name.assign_ptr(var->str_value_, static_cast<int32_t>(var->str_len_));
|
||||
} else if (T_OBJ_ACCESS_REF == var->type_) { // Oracle mode
|
||||
const ParseNode* name_node = NULL;
|
||||
if (OB_ISNULL(name_node = var->children_[0]) || OB_UNLIKELY(var->children_[1] != NULL)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name not an identifier type");
|
||||
} else if (OB_UNLIKELY(name_node->type_ != T_IDENT)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name not an identifier type");
|
||||
} else {
|
||||
var_node.is_system_variable_ = true;
|
||||
var_name.assign_ptr(name_node->str_value_, static_cast<int32_t>(name_node->str_len_));
|
||||
}
|
||||
} else {
|
||||
var_node.is_system_variable_ = (T_SYSTEM_VARIABLE == var->type_);
|
||||
var_name.assign_ptr(var->str_value_, static_cast<int32_t>(var->str_len_));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ob_write_string(*allocator_, var_name, var_node.variable_name_))) {
|
||||
LOG_WARN("Can not malloc space for variable name", K(ret));
|
||||
} else {
|
||||
ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, var_node.variable_name_);
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(set_node.children_[1])) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("value node is NULL", K(ret));
|
||||
} else if (T_DEFAULT == set_node.children_[1]->type_) {
|
||||
// set system_variable = default
|
||||
var_node.is_set_default_ = true;
|
||||
} else if (var_node.is_system_variable_) {
|
||||
ParseNode value_node;
|
||||
if (T_IDENT == set_node.children_[1]->type_) {
|
||||
MEMCPY(&value_node, set_node.children_[1], sizeof(ParseNode));
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else if (T_COLUMN_REF == set_node.children_[1]->type_) {
|
||||
if (NULL == set_node.children_[1]->children_[0] && NULL == set_node.children_[1]->children_[1] &&
|
||||
NULL != set_node.children_[1]->children_[2]) {
|
||||
MEMCPY(&value_node, set_node.children_[1]->children_[2], sizeof(ParseNode));
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node.children_[1], sizeof(ParseNode));
|
||||
}
|
||||
} else if (T_OBJ_ACCESS_REF == set_node.children_[1]->type_) { // Oracle mode
|
||||
if (OB_ISNULL(set_node.children_[1]->children_[0]) ||
|
||||
OB_UNLIKELY(set_node.children_[1]->children_[1] != NULL)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable value not a varchar nor identifier type");
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node.children_[1]->children_[0], sizeof(ParseNode));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (T_IDENT == set_node.children_[1]->children_[0]->type_) {
|
||||
value_node.type_ = T_VARCHAR;
|
||||
} else if (T_FUN_SYS == set_node.children_[1]->children_[0]->type_) {
|
||||
// do nothing
|
||||
} else {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable value type");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MEMCPY(&value_node, set_node.children_[1], sizeof(ParseNode));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == var_node.variable_name_.case_compare("ob_compatibility_mode") &&
|
||||
0 == strncasecmp(
|
||||
value_node.str_value_, "oracle", std::min(static_cast<int32_t>(value_node.str_len_), 6))) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Not support oracle mode");
|
||||
} else if (OB_FAIL(
|
||||
ObResolverUtils::resolve_const_expr(params_, value_node, var_node.value_expr_, NULL))) {
|
||||
LOG_WARN("resolve variable value failed", K(ret));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(ObResolverUtils::resolve_const_expr(
|
||||
params_, *set_node.children_[1], var_node.value_expr_, NULL))) {
|
||||
LOG_WARN("resolve variable value failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObVariableSetResolver::resolve_set_names(const ParseNode &set_node,
|
||||
ObVariableSetStmt::NamesSetNode &names_node)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(set_node.children_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_RESV_LOG(WARN, "set_node.children_ is null.", K(ret));
|
||||
} else if (OB_ISNULL(set_node.children_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_RESV_LOG(WARN, "set_node.children_[0] is null.", K(ret));
|
||||
} else {
|
||||
if (T_SET_NAMES == set_node.type_) {
|
||||
// SET NAMES
|
||||
names_node.is_set_names_ = true;
|
||||
if (T_DEFAULT == set_node.children_[0]->type_) {
|
||||
names_node.is_default_charset_ = true;
|
||||
} else {
|
||||
names_node.is_default_charset_ = false;
|
||||
ObString charset;
|
||||
charset.assign_ptr(
|
||||
set_node.children_[0]->str_value_, static_cast<int32_t>(set_node.children_[0]->str_len_));
|
||||
if (0 == charset.case_compare("utf16")) {
|
||||
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
||||
LOG_USER_ERROR(OB_ERR_WRONG_VALUE_FOR_VAR,
|
||||
static_cast<int>(strlen("character_set_client")),
|
||||
"character_set_client",
|
||||
charset.length(),
|
||||
charset.ptr());
|
||||
} else {
|
||||
names_node.charset_ = charset;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (NULL == set_node.children_[1]) {
|
||||
names_node.is_default_collation_ = true;
|
||||
} else {
|
||||
names_node.is_default_collation_ = false;
|
||||
ObString collation;
|
||||
collation.assign_ptr(
|
||||
set_node.children_[1]->str_value_, static_cast<int32_t>(set_node.children_[1]->str_len_));
|
||||
names_node.collation_ = collation;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// SET CHARACTER SET
|
||||
names_node.is_set_names_ = false;
|
||||
if (T_DEFAULT == set_node.children_[0]->type_) {
|
||||
names_node.is_default_charset_ = true;
|
||||
} else {
|
||||
names_node.is_default_charset_ = false;
|
||||
names_node.charset_.assign_ptr(set_node.children_[0]->str_value_,
|
||||
static_cast<int32_t>(set_node.children_[0]->str_len_));
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("resolve set names", K(names_node));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ObAlterSessionSetResolver::ObAlterSessionSetResolver(ObResolverParams& params) : ObStmtResolver(params)
|
||||
{}
|
||||
|
||||
@ -252,7 +332,8 @@ int ObAlterSessionSetResolver::resolve(const ParseNode& parse_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(var_node))) {
|
||||
if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(
|
||||
ObVariableSetStmt::make_variable_name_node(var_node)))) {
|
||||
LOG_WARN("Add set entry failed", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,9 @@ public:
|
||||
virtual ~ObVariableSetResolver();
|
||||
|
||||
virtual int resolve(const ParseNode& parse_tree);
|
||||
int resolve_set_variable(const ParseNode &set_node, ObVariableSetStmt::VariableSetNode &var_node,
|
||||
ObVariableSetStmt* variable_set_stmt);
|
||||
int resolve_set_names(const ParseNode &set_node, ObVariableSetStmt::NamesSetNode &names_node);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObVariableSetResolver);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
namespace oceanbase {
|
||||
using namespace common;
|
||||
namespace sql {
|
||||
int ObVariableSetStmt::get_variable_node(int64_t index, ObVariableSetStmt::VariableSetNode& var_node) const
|
||||
int ObVariableSetStmt::get_variable_node(int64_t index, ObVariableSetStmt::VariableNamesSetNode& var_node) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(index < 0 || index >= variable_nodes_.count())) {
|
||||
|
||||
@ -41,6 +41,47 @@ public:
|
||||
ObRawExpr* value_expr_;
|
||||
bool is_set_default_;
|
||||
};
|
||||
class NamesSetNode {
|
||||
public:
|
||||
NamesSetNode()
|
||||
: is_set_names_(true),
|
||||
is_default_charset_(true),
|
||||
is_default_collation_(true),
|
||||
charset_(),
|
||||
collation_()
|
||||
{}
|
||||
virtual ~NamesSetNode()
|
||||
{}
|
||||
TO_STRING_KV(K_(is_set_names), K_(is_default_charset), K_(is_default_collation), K_(charset), K_(collation));
|
||||
|
||||
bool is_set_names_; // SET NAMES or SET CHARSET?
|
||||
bool is_default_charset_;
|
||||
bool is_default_collation_;
|
||||
common::ObString charset_;
|
||||
common::ObString collation_;
|
||||
};
|
||||
|
||||
class VariableNamesSetNode {
|
||||
public:
|
||||
VariableNamesSetNode()
|
||||
: is_set_variable_(true),
|
||||
var_set_node_(),
|
||||
names_set_node_()
|
||||
{}
|
||||
VariableNamesSetNode(bool is_set_variable, const VariableSetNode &var_node,
|
||||
const NamesSetNode &names_node)
|
||||
: is_set_variable_(is_set_variable),
|
||||
var_set_node_(var_node),
|
||||
names_set_node_(names_node)
|
||||
{}
|
||||
virtual ~VariableNamesSetNode()
|
||||
{}
|
||||
TO_STRING_KV(K_(is_set_variable), K_(var_set_node), K_(names_set_node));
|
||||
|
||||
bool is_set_variable_; // set variables or set names
|
||||
VariableSetNode var_set_node_;
|
||||
NamesSetNode names_set_node_;
|
||||
};
|
||||
|
||||
ObVariableSetStmt()
|
||||
: ObDDLStmt(stmt::T_VARIABLE_SET),
|
||||
@ -51,6 +92,12 @@ public:
|
||||
virtual ~ObVariableSetStmt()
|
||||
{}
|
||||
|
||||
static inline VariableNamesSetNode make_variable_name_node(VariableSetNode& var_set_node) {
|
||||
return VariableNamesSetNode(true, var_set_node, NamesSetNode());
|
||||
}
|
||||
static inline VariableNamesSetNode make_variable_name_node(NamesSetNode& names_set_node) {
|
||||
return VariableNamesSetNode(false, VariableSetNode(), names_set_node);
|
||||
}
|
||||
inline void set_actual_tenant_id(uint64_t actual_tenant_id)
|
||||
{
|
||||
actual_tenant_id_ = actual_tenant_id;
|
||||
@ -59,9 +106,9 @@ public:
|
||||
{
|
||||
return actual_tenant_id_;
|
||||
}
|
||||
inline int add_variable_node(const VariableSetNode& node);
|
||||
inline int add_variable_node(const VariableNamesSetNode& node);
|
||||
inline int64_t get_variables_size() const;
|
||||
int get_variable_node(int64_t index, VariableSetNode& node) const;
|
||||
int get_variable_node(int64_t index, VariableNamesSetNode& node) const;
|
||||
inline void set_has_global_variable(bool has_global_variable)
|
||||
{
|
||||
has_global_variable_ = has_global_variable;
|
||||
@ -86,7 +133,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
const common::ObIArray<VariableSetNode>& get_variable_nodes() const
|
||||
const common::ObIArray<VariableNamesSetNode>& get_variable_nodes() const
|
||||
{
|
||||
return variable_nodes_;
|
||||
}
|
||||
@ -98,13 +145,13 @@ public:
|
||||
|
||||
private:
|
||||
uint64_t actual_tenant_id_;
|
||||
common::ObArray<VariableSetNode, common::ModulePageAllocator, true> variable_nodes_;
|
||||
common::ObArray<VariableNamesSetNode, common::ModulePageAllocator, true> variable_nodes_;
|
||||
bool has_global_variable_;
|
||||
obrpc::ObModifySysVarArg modify_sysvar_arg_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ObVariableSetStmt);
|
||||
};
|
||||
|
||||
inline int ObVariableSetStmt::add_variable_node(const VariableSetNode& node)
|
||||
inline int ObVariableSetStmt::add_variable_node(const VariableNamesSetNode& node)
|
||||
{
|
||||
return variable_nodes_.push_back(node);
|
||||
}
|
||||
|
||||
@ -129,20 +129,26 @@ int ObCreateTenantResolver::resolve(const ParseNode& parse_tree)
|
||||
|
||||
bool is_oracle_mode = false;
|
||||
if (OB_SUCC(ret)) {
|
||||
for (int64_t i = 0; i < mystmt->get_sys_var_nodes().count(); i++) {
|
||||
const ObVariableSetStmt::VariableSetNode& node = mystmt->get_sys_var_nodes().at(i);
|
||||
if (0 == node.variable_name_.case_compare("ob_compatibility_mode")) {
|
||||
ObConstRawExpr* const_expr = static_cast<ObConstRawExpr*>(node.value_expr_);
|
||||
if (nullptr == const_expr) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("const expr is null", K(ret));
|
||||
} else {
|
||||
ObObj value = const_expr->get_value();
|
||||
ObString str;
|
||||
if (OB_FAIL(value.get_string(str))) {
|
||||
LOG_WARN("get string failed", K(ret));
|
||||
} else if (0 == str.case_compare("oracle")) {
|
||||
is_oracle_mode = true;
|
||||
for (int64_t i = 0; i < mystmt->get_sys_var_nodes().count() && OB_SUCC(ret); i++) {
|
||||
const ObVariableSetStmt::VariableNamesSetNode& var_names_node = mystmt->get_sys_var_nodes().at(i);
|
||||
if (OB_UNLIKELY(!var_names_node.is_set_variable_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("not allow to set names when create tenant according to symtax", K(ret));
|
||||
} else {
|
||||
const ObVariableSetStmt::VariableSetNode& node = var_names_node.var_set_node_;
|
||||
if (0 == node.variable_name_.case_compare("ob_compatibility_mode")) {
|
||||
ObConstRawExpr* const_expr = static_cast<ObConstRawExpr*>(node.value_expr_);
|
||||
if (nullptr == const_expr) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("const expr is null", K(ret));
|
||||
} else {
|
||||
ObObj value = const_expr->get_value();
|
||||
ObString str;
|
||||
if (OB_FAIL(value.get_string(str))) {
|
||||
LOG_WARN("get string failed", K(ret));
|
||||
} else if (0 == str.case_compare("oracle")) {
|
||||
is_oracle_mode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,15 +59,15 @@ public:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int add_sys_var_node(const ObVariableSetStmt::VariableSetNode& node)
|
||||
int add_sys_var_node(const ObVariableSetStmt::VariableNamesSetNode& node)
|
||||
{
|
||||
return sys_var_nodes_.push_back(node);
|
||||
}
|
||||
const common::ObIArray<ObVariableSetStmt::VariableSetNode>& get_sys_var_nodes() const
|
||||
const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& get_sys_var_nodes() const
|
||||
{
|
||||
return sys_var_nodes_;
|
||||
}
|
||||
int assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableSetNode>& other);
|
||||
int assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& other);
|
||||
int set_default_tablegroup_name(const common::ObString& tablegroup_name);
|
||||
virtual obrpc::ObDDLArg& get_ddl_arg()
|
||||
{
|
||||
@ -76,7 +76,7 @@ public:
|
||||
|
||||
private:
|
||||
obrpc::ObCreateTenantArg create_tenant_arg_;
|
||||
common::ObArray<ObVariableSetStmt::VariableSetNode, common::ModulePageAllocator, true> sys_var_nodes_;
|
||||
common::ObArray<ObVariableSetStmt::VariableNamesSetNode, common::ModulePageAllocator, true> sys_var_nodes_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ObCreateTenantStmt);
|
||||
};
|
||||
|
||||
@ -85,7 +85,7 @@ inline obrpc::ObCreateTenantArg& ObCreateTenantStmt::get_create_tenant_arg()
|
||||
return create_tenant_arg_;
|
||||
}
|
||||
|
||||
inline int ObCreateTenantStmt::assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableSetNode>& other)
|
||||
inline int ObCreateTenantStmt::assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& other)
|
||||
{
|
||||
return sys_var_nodes_.assign(other);
|
||||
}
|
||||
|
||||
@ -99,15 +99,15 @@ public:
|
||||
{
|
||||
return modify_tenant_arg_.check_normal_tenant_can_do(normal_can_do);
|
||||
}
|
||||
int add_sys_var_node(const ObVariableSetStmt::VariableSetNode& node)
|
||||
int add_sys_var_node(const ObVariableSetStmt::VariableNamesSetNode& node)
|
||||
{
|
||||
return sys_var_nodes_.push_back(node);
|
||||
}
|
||||
const common::ObIArray<ObVariableSetStmt::VariableSetNode>& get_sys_var_nodes() const
|
||||
const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& get_sys_var_nodes() const
|
||||
{
|
||||
return sys_var_nodes_;
|
||||
}
|
||||
int assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableSetNode>& other);
|
||||
int assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& other);
|
||||
int set_default_tablegroup_name(const common::ObString& tablegroup_name);
|
||||
|
||||
virtual obrpc::ObDDLArg& get_ddl_arg()
|
||||
@ -119,7 +119,7 @@ public:
|
||||
private:
|
||||
bool for_current_tenant_;
|
||||
obrpc::ObModifyTenantArg modify_tenant_arg_;
|
||||
common::ObArray<ObVariableSetStmt::VariableSetNode, common::ModulePageAllocator, true> sys_var_nodes_;
|
||||
common::ObArray<ObVariableSetStmt::VariableNamesSetNode, common::ModulePageAllocator, true> sys_var_nodes_;
|
||||
ObModifyTenantSpecialOption special_option_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ObModifyTenantStmt);
|
||||
};
|
||||
@ -145,7 +145,7 @@ inline const common::ObString& ObModifyTenantStmt::get_new_tenant_name() const
|
||||
return modify_tenant_arg_.new_tenant_name_;
|
||||
}
|
||||
|
||||
inline int ObModifyTenantStmt::assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableSetNode>& other)
|
||||
inline int ObModifyTenantStmt::assign_variable_nodes(const common::ObIArray<ObVariableSetStmt::VariableNamesSetNode>& other)
|
||||
{
|
||||
return sys_var_nodes_.assign(other);
|
||||
}
|
||||
|
||||
@ -81,7 +81,6 @@
|
||||
#include "sql/resolver/cmd/ob_show_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_alter_system_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_kill_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_set_names_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_set_transaction_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_bootstrap_resolver.h"
|
||||
#include "sql/resolver/cmd/ob_empty_query_resolver.h"
|
||||
@ -643,12 +642,6 @@ int ObResolver::resolve(IsPrepared if_prepared, const ParseNode& parse_tree, ObS
|
||||
REGISTER_STMT_RESOLVER(AlterSessionSet);
|
||||
break;
|
||||
}
|
||||
case T_SET_NAMES:
|
||||
// fall through
|
||||
case T_SET_CHARSET: {
|
||||
REGISTER_STMT_RESOLVER(SetNames);
|
||||
break;
|
||||
}
|
||||
case T_KILL: {
|
||||
REGISTER_STMT_RESOLVER(Kill);
|
||||
break;
|
||||
|
||||
@ -594,6 +594,9 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
int create_stmt<ObSelectStmt>(ObSelectStmt*& stmt);
|
||||
|
||||
inline int free_stmt(ObSelectStmt* stmt)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
|
||||
@ -123,7 +123,6 @@ OB_STMT_TYPE_DEF(T_ALTER_TABLEGROUP, get_alter_tablegroup_stmt_need_privs, 109)
|
||||
OB_STMT_TYPE_DEF(T_TRUNCATE_TABLE, get_truncate_table_stmt_need_privs, 110)
|
||||
OB_STMT_TYPE_DEF(T_RENAME_TABLE, get_rename_table_stmt_need_privs, 111)
|
||||
OB_STMT_TYPE_DEF(T_CREATE_TABLE_LIKE, get_create_table_like_stmt_need_privs, 112)
|
||||
OB_STMT_TYPE_DEF(T_SET_NAMES, no_priv_needed, 113)
|
||||
OB_STMT_TYPE_DEF(T_CLEAR_LOCATION_CACHE, get_sys_tenant_alter_system_priv, 114)
|
||||
OB_STMT_TYPE_DEF(T_RELOAD_GTS, get_sys_tenant_alter_system_priv, 115)
|
||||
OB_STMT_TYPE_DEF(T_RELOAD_UNIT, get_sys_tenant_alter_system_priv, 116)
|
||||
|
||||
Reference in New Issue
Block a user