From 72302550bbc70e24dd9ec92fb2c0070cabaab1ba Mon Sep 17 00:00:00 2001 From: wjhh2008 Date: Thu, 28 Mar 2024 09:46:01 +0000 Subject: [PATCH] [CP] [CP] Support set names with variables --- src/pl/parser/pl_parser_mysql_mode.y | 9 +- .../engine/cmd/ob_variable_set_executor.cpp | 15 ++ src/sql/engine/cmd/ob_variable_set_executor.h | 1 + src/sql/parser/sql_parser_mysql_mode.y | 31 ++-- .../resolver/cmd/ob_variable_set_resolver.cpp | 25 +++ .../resolver/cmd/ob_variable_set_resolver.h | 1 + src/sql/resolver/cmd/ob_variable_set_stmt.h | 5 +- unittest/sql/parser/print_parser_tree.result | 39 +++-- unittest/sql/parser/test_parser.result | 144 ++++++++++++------ 9 files changed, 187 insertions(+), 83 deletions(-) diff --git a/src/pl/parser/pl_parser_mysql_mode.y b/src/pl/parser/pl_parser_mysql_mode.y index 483bb7a4a..4bc2f8d35 100644 --- a/src/pl/parser/pl_parser_mysql_mode.y +++ b/src/pl/parser/pl_parser_mysql_mode.y @@ -445,8 +445,15 @@ sql_stmt: $$ = sql_stmt; } if(T_VARIABLE_SET == $$->type_) { + int64_t child_cnt = $$->num_child_; for(int64_t i = 0; i < $$->num_child_; ++i) { - if(OB_UNLIKELY(NULL == $$->children_[i] || NULL == $$->children_[i]->children_[1])) { + if (T_SET_NAMES == $$->children_[i]->type_ || T_SET_CHARSET == $$->children_[i]->type_) { + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SQL_STMT, 1, sql_stmt); + if (child_cnt > 1) { + obpl_mysql_yyerror(&@1, parse_ctx, "Syntax Error\n"); + YYERROR; + } + } else if(OB_UNLIKELY(NULL == $$->children_[i] || NULL == $$->children_[i]->children_[1])) { YY_UNEXPECTED_ERROR("value node in SET statement is NULL"); } else { obpl_mysql_wrap_get_user_var_into_subquery(parse_ctx, $$->children_[i]->children_[1]); diff --git a/src/sql/engine/cmd/ob_variable_set_executor.cpp b/src/sql/engine/cmd/ob_variable_set_executor.cpp index 3656371ba..46a207bd9 100644 --- a/src/sql/engine/cmd/ob_variable_set_executor.cpp +++ b/src/sql/engine/cmd/ob_variable_set_executor.cpp @@ -35,6 +35,7 @@ #include "lib/timezone/ob_oracle_format_models.h" #include "observer/ob_server.h" #include "sql/rewrite/ob_transform_pre_process.h" +#include "sql/engine/cmd/ob_set_names_executor.h" using namespace oceanbase::common; using namespace oceanbase::share; @@ -73,6 +74,16 @@ ObVariableSetExecutor::~ObVariableSetExecutor() { } +int ObVariableSetExecutor::do_set_names(ObExecContext &ctx, ObSetNamesStmt &stmt) +{ + int ret = OB_SUCCESS; + ObSetNamesExecutor executor; + if (OB_FAIL(executor.execute(ctx, stmt))) { + LOG_WARN("fail to set names", K(ret)); + } + return ret; +} + int ObVariableSetExecutor::execute(ObExecContext &ctx, ObVariableSetStmt &stmt) { int ret = OB_SUCCESS; @@ -114,6 +125,10 @@ int ObVariableSetExecutor::execute(ObExecContext &ctx, ObVariableSetStmt &stmt) ObVariableSetStmt::VariableSetNode &node = tmp_node; if (OB_FAIL(stmt.get_variable_node(i, node))) { LOG_WARN("fail to get variable node", K(i), K(ret)); + } else if (OB_NOT_NULL(node.set_names_stmt_)) { + if (OB_FAIL(do_set_names(ctx, *node.set_names_stmt_))) { + LOG_WARN("fail to set names", K(ret)); + } } else { ObObj value_obj; ObBasicSysVar *sys_var = NULL; diff --git a/src/sql/engine/cmd/ob_variable_set_executor.h b/src/sql/engine/cmd/ob_variable_set_executor.h index b54ea72bf..9972c1a6e 100644 --- a/src/sql/engine/cmd/ob_variable_set_executor.h +++ b/src/sql/engine/cmd/ob_variable_set_executor.h @@ -121,6 +121,7 @@ private: common::ObIAllocator &calc_buf, common::ObMySQLProxy &sql_proxy, const ObValidatePasswordCtx &password_ctx); + int do_set_names(ObExecContext &ctx, ObSetNamesStmt &stmt); private: DISALLOW_COPY_AND_ASSIGN(ObVariableSetExecutor); }; diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index f45e28d8d..6ab6a5944 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -484,7 +484,6 @@ END_P SET_VAR DELIMITER %type zone_action upgrade_action %type opt_index_name opt_key_or_index opt_index_options opt_primary opt_all %type charset_key database_key charset_name charset_name_or_default collation_name databases_or_schemas trans_param_name trans_param_value -%type set_names_stmt set_charset_stmt %type charset_introducer complex_string_literal literal number_literal now_or_signed_literal signed_literal %type create_tablegroup_stmt drop_tablegroup_stmt alter_tablegroup_stmt default_tablegroup %type set_transaction_stmt transaction_characteristics transaction_access_mode isolation_level @@ -663,8 +662,6 @@ stmt: | create_resource_stmt { $$ = $1; check_question_mark($$, result); } | alter_resource_stmt { $$ = $1; check_question_mark($$, result); } | drop_resource_stmt { $$ = $1; check_question_mark($$, result); } - | set_names_stmt { $$ = $1; check_question_mark($$, result); } - | set_charset_stmt { $$ = $1; check_question_mark($$, result); } | create_tablegroup_stmt { $$ = $1; check_question_mark($$, result); } | drop_tablegroup_stmt { $$ = $1; check_question_mark($$, result); } | alter_tablegroup_stmt { $$ = $1; check_question_mark($$, result); } @@ -8183,7 +8180,7 @@ UNDEFINED { $$ = NULL; } | TEMPTABLE { $$ = NULL; } opt_definer: -DEFINER COMP_EQ user +DEFINER COMP_EQ user_with_host_name { (void)($3); $$ = NULL; @@ -15020,6 +15017,15 @@ USER_VARIABLE to_or_eq expr malloc_non_terminal_node($$, result->malloc_pool_, T_VAR_VAL, 2, $1, $3); $$->value_ = 2; } +| NAMES charset_name_or_default opt_collation +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_NAMES, 2, $2, $3); +} +| charset_key charset_name_or_default +{ + (void)($1); + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_CHARSET, 1, $2); +}; ; sys_var_and_val: @@ -18815,23 +18821,6 @@ extension: //} ; -//////////////////////////////////////////////////////////////// -/* SET NAMES 'charset_name' [COLLATE 'collation_name'] */ -set_names_stmt: -SET NAMES charset_name_or_default opt_collation -{ - malloc_non_terminal_node($$, result->malloc_pool_, T_SET_NAMES, 2, $3, $4); -}; - -//////////////////////////////////////////////////////////////// -/* SET CHARACTER SET charset_name */ -set_charset_stmt: -SET charset_key charset_name_or_default -{ - (void)($2); - malloc_non_terminal_node($$, result->malloc_pool_, T_SET_CHARSET, 1, $3); -}; - ////////////////////////////// set_transaction_stmt: SET TRANSACTION transaction_characteristics diff --git a/src/sql/resolver/cmd/ob_variable_set_resolver.cpp b/src/sql/resolver/cmd/ob_variable_set_resolver.cpp index 6e8bcf045..949ce25d4 100644 --- a/src/sql/resolver/cmd/ob_variable_set_resolver.cpp +++ b/src/sql/resolver/cmd/ob_variable_set_resolver.cpp @@ -18,6 +18,7 @@ #include "sql/resolver/cmd/ob_variable_set_stmt.h" #include "sql/session/ob_sql_session_info.h" #include "sql/resolver/expr/ob_raw_expr_resolver_impl.h" +#include "sql/resolver/cmd/ob_set_names_resolver.h" namespace oceanbase { using namespace common; @@ -34,6 +35,26 @@ ObVariableSetResolver::~ObVariableSetResolver() { } +int ObVariableSetResolver::resolve_set_names(const ParseNode &parse_tree) +{ + int ret = OB_SUCCESS; + ObSetNamesResolver set_names_resolver(params_); + if (OB_ISNULL(stmt_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt not created in resolver", K(ret)); + } else if (OB_FAIL(set_names_resolver.resolve(parse_tree))) { + LOG_WARN("fail to resolve", K(ret)); + } else { + ObVariableSetStmt *variable_set_stmt = static_cast(stmt_); + ObVariableSetStmt::VariableSetNode var_node; + var_node.set_names_stmt_ = static_cast(set_names_resolver.get_basic_stmt()); + if (OB_FAIL(variable_set_stmt->add_variable_node(var_node))) { + LOG_WARN("Add set entry failed", K(ret)); + } + } + return ret; +} + int ObVariableSetResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; @@ -57,6 +78,10 @@ int ObVariableSetResolver::resolve(const ParseNode &parse_tree) if (OB_ISNULL(set_node = parse_tree.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("set node is NULL", K(ret)); + } else if (T_SET_NAMES == set_node->type_ || T_SET_CHARSET == set_node->type_) { + if (OB_FAIL(resolve_set_names(*set_node))) { + LOG_WARN("fail to resolve set names", 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_)); diff --git a/src/sql/resolver/cmd/ob_variable_set_resolver.h b/src/sql/resolver/cmd/ob_variable_set_resolver.h index 6327c88e0..ea672e825 100644 --- a/src/sql/resolver/cmd/ob_variable_set_resolver.h +++ b/src/sql/resolver/cmd/ob_variable_set_resolver.h @@ -29,6 +29,7 @@ public: int resolve_value_expr(ParseNode &val_node, ObRawExpr *&value_expr); int resolve_subquery_info(const ObIArray &subquery_info, ObRawExpr *&value_expr); private: + int resolve_set_names(const ParseNode &parse_tree); DISALLOW_COPY_AND_ASSIGN(ObVariableSetResolver); }; diff --git a/src/sql/resolver/cmd/ob_variable_set_stmt.h b/src/sql/resolver/cmd/ob_variable_set_stmt.h index a9db7dfe7..ebf670d2f 100644 --- a/src/sql/resolver/cmd/ob_variable_set_stmt.h +++ b/src/sql/resolver/cmd/ob_variable_set_stmt.h @@ -17,6 +17,7 @@ #include "lib/container/ob_array.h" #include "sql/resolver/ddl/ob_ddl_stmt.h" #include "share/system_variable/ob_system_variable.h" +#include "sql/resolver/cmd/ob_set_names_stmt.h" namespace oceanbase { @@ -32,7 +33,8 @@ public: is_system_variable_(false), set_scope_(share::ObSetVar::SET_SCOPE_NEXT_TRANS), value_expr_(NULL), - is_set_default_(false) + is_set_default_(false), + set_names_stmt_(NULL) {} virtual ~VariableSetNode() {} TO_STRING_KV(K_(variable_name), K_(is_system_variable), @@ -43,6 +45,7 @@ public: share::ObSetVar::SetScopeType set_scope_; ObRawExpr *value_expr_; bool is_set_default_; + ObSetNamesStmt *set_names_stmt_; }; ObVariableSetStmt() : ObDDLStmt(stmt::T_VARIABLE_SET), diff --git a/unittest/sql/parser/print_parser_tree.result b/unittest/sql/parser/print_parser_tree.result index 367ecf90f..98417beba 100644 --- a/unittest/sql/parser/print_parser_tree.result +++ b/unittest/sql/parser/print_parser_tree.result @@ -2612,58 +2612,65 @@ set names latin1; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_NAMES], str_value_=[], value=[0] - |--[0],[T_CHAR_CHARSET], str_value_=[latin1], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_NAMES], str_value_=[], value=[9223372036854775807] + |--[0],[T_CHAR_CHARSET], str_value_=[latin1], value=[9223372036854775807] ************** Case 131 *************** set names 'latin1'; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_NAMES], str_value_=[], value=[0] - |--[0],[T_VARCHAR], str_value_=[latin1], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_NAMES], str_value_=[], value=[9223372036854775807] + |--[0],[T_VARCHAR], str_value_=[latin1], value=[9223372036854775807] ************** Case 132 *************** set names utf8 collate 'utf8_general_ci'; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_NAMES], str_value_=[], value=[0] - |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] - |--[1],[T_COLLATION], str_value_=[utf8_general_ci], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_NAMES], str_value_=[], value=[9223372036854775807] + |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] + |--[1],[T_COLLATION], str_value_=[utf8_general_ci], value=[9223372036854775807] ************** Case 133 *************** set names utf8 collate utf8_general_ci; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_NAMES], str_value_=[], value=[0] - |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] - |--[1],[T_COLLATION], str_value_=[utf8_general_ci], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_NAMES], str_value_=[], value=[9223372036854775807] + |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] + |--[1],[T_COLLATION], str_value_=[utf8_general_ci], value=[9223372036854775807] ************** Case 134 *************** set character set utf8; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_CHARSET], str_value_=[], value=[0] - |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_CHARSET], str_value_=[], value=[9223372036854775807] + |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] ************** Case 135 *************** set character set 'utf8'; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_CHARSET], str_value_=[], value=[0] - |--[0],[T_VARCHAR], str_value_=[utf8], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_CHARSET], str_value_=[], value=[9223372036854775807] + |--[0],[T_VARCHAR], str_value_=[utf8], value=[9223372036854775807] ************** Case 136 *************** set charset utf8; question_mask_size: 0 |--[0],[T_STMT_LIST], str_value_=[], value=[9223372036854775807] - |--[0],[T_SET_CHARSET], str_value_=[], value=[0] - |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] + |--[0],[T_VARIABLE_SET], str_value_=[], value=[0] + |--[0],[T_SET_CHARSET], str_value_=[], value=[9223372036854775807] + |--[0],[T_CHAR_CHARSET], str_value_=[utf8], value=[9223372036854775807] ************** Case 137 *************** select _utf8 'abc', _utf8mb4 'def' collate utf8mb4_general_ci from t1 where c1 collate utf8_bin = 'xyz' collate utf8_bin; diff --git a/unittest/sql/parser/test_parser.result b/unittest/sql/parser/test_parser.result index ec7967bb5..a8b858430 100644 --- a/unittest/sql/parser/test_parser.result +++ b/unittest/sql/parser/test_parser.result @@ -17428,18 +17428,26 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_NAMES", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_CHAR_CHARSET", + "type":"T_SET_NAMES", "int_val":9223372036854775807, - "str_len":6, - "str_val":"latin1" - }, - { } + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_CHAR_CHARSET", + "int_val":9223372036854775807, + "str_len":6, + "str_val":"latin1" + }, + { } + ] + } ] } ] @@ -17454,18 +17462,26 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_NAMES", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_VARCHAR", + "type":"T_SET_NAMES", "int_val":9223372036854775807, - "str_len":6, - "str_val":"latin1" - }, - { } + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_VARCHAR", + "int_val":9223372036854775807, + "str_len":6, + "str_val":"latin1" + }, + { } + ] + } ] } ] @@ -17480,22 +17496,30 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_NAMES", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_CHAR_CHARSET", + "type":"T_SET_NAMES", "int_val":9223372036854775807, - "str_len":4, - "str_val":"utf8" - }, - { - "type":"T_COLLATION", - "int_val":9223372036854775807, - "str_len":15, - "str_val":"utf8_general_ci" + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_CHAR_CHARSET", + "int_val":9223372036854775807, + "str_len":4, + "str_val":"utf8" + }, + { + "type":"T_COLLATION", + "int_val":9223372036854775807, + "str_len":15, + "str_val":"utf8_general_ci" + } + ] } ] } @@ -17511,22 +17535,30 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_NAMES", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_CHAR_CHARSET", + "type":"T_SET_NAMES", "int_val":9223372036854775807, - "str_len":4, - "str_val":"utf8" - }, - { - "type":"T_COLLATION", - "int_val":9223372036854775807, - "str_len":15, - "str_val":"utf8_general_ci" + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_CHAR_CHARSET", + "int_val":9223372036854775807, + "str_len":4, + "str_val":"utf8" + }, + { + "type":"T_COLLATION", + "int_val":9223372036854775807, + "str_len":15, + "str_val":"utf8_general_ci" + } + ] } ] } @@ -17542,16 +17574,24 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_CHARSET", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_CHAR_CHARSET", + "type":"T_SET_CHARSET", "int_val":9223372036854775807, - "str_len":4, - "str_val":"utf8" + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_CHAR_CHARSET", + "int_val":9223372036854775807, + "str_len":4, + "str_val":"utf8" + } + ] } ] } @@ -17567,16 +17607,24 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_CHARSET", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_VARCHAR", + "type":"T_SET_CHARSET", "int_val":9223372036854775807, - "str_len":4, - "str_val":"utf8" + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_VARCHAR", + "int_val":9223372036854775807, + "str_len":4, + "str_val":"utf8" + } + ] } ] } @@ -17592,16 +17640,24 @@ question_mask_size: 0 "str_val":"", "children": [ { - "type":"T_SET_CHARSET", + "type":"T_VARIABLE_SET", "int_val":0, "str_len":0, "str_val":"", "children": [ { - "type":"T_CHAR_CHARSET", + "type":"T_SET_CHARSET", "int_val":9223372036854775807, - "str_len":4, - "str_val":"utf8" + "str_len":0, + "str_val":"", + "children": [ + { + "type":"T_CHAR_CHARSET", + "int_val":9223372036854775807, + "str_len":4, + "str_val":"utf8" + } + ] } ] }