Commit 054d00a9 authored by Alexander Barkov's avatar Alexander Barkov

A fix for MDEV-10411 Providing compatibility for basic PL/SQL constructs (Part...

A fix for MDEV-10411 Providing compatibility for basic PL/SQL constructs (Part 6: Assignment operator)

Fixed that a crash in this script:

SET sql_mode=ORACLE;
max_sort_length:= 1024;
parent 7fa1ad14
SET sql_mode=oracle;
#
# MDEV-10411 Providing compatibility for basic PL/SQL constructs
# Part 6: Assignment operator
#
max_sort_length:=1030;
SELECT @@max_sort_length;
@@max_sort_length
1030
max_sort_length:=DEFAULT;
#
# Testing that SP variables shadow global variables in assignments
#
CREATE PROCEDURE p1
AS
BEGIN
max_sort_length:=1030;
DECLARE
max_sort_length INT DEFAULT 1031;
BEGIN
SELECT @@max_sort_length, max_sort_length;
max_sort_length:=1032;
SELECT @@max_sort_length, max_sort_length;
END;
SELECT @@max_sort_length;
max_sort_length:= DEFAULT;
END;
$$
CALL p1();
@@max_sort_length max_sort_length
1030 1031
@@max_sort_length max_sort_length
1030 1032
@@max_sort_length
1030
DROP PROCEDURE p1;
#
# End of MDEV-10411 Providing compatibility for basic PL/SQL constructs (part 6)
#
SET sql_mode=oracle;
--echo #
--echo # MDEV-10411 Providing compatibility for basic PL/SQL constructs
--echo # Part 6: Assignment operator
--echo #
max_sort_length:=1030;
SELECT @@max_sort_length;
max_sort_length:=DEFAULT;
--echo #
--echo # Testing that SP variables shadow global variables in assignments
--echo #
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
max_sort_length:=1030;
DECLARE
max_sort_length INT DEFAULT 1031;
BEGIN
SELECT @@max_sort_length, max_sort_length;
max_sort_length:=1032;
SELECT @@max_sort_length, max_sort_length;
END;
SELECT @@max_sort_length;
max_sort_length:= DEFAULT;
END;
$$
DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
--echo #
--echo # End of MDEV-10411 Providing compatibility for basic PL/SQL constructs (part 6)
--echo #
...@@ -5922,6 +5922,35 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v) ...@@ -5922,6 +5922,35 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
} }
/*
Perform assignment for a trigger, a system variable, or an SP variable.
"variable" be previously set by init_internal_variable(variable, name).
*/
bool LEX::set_variable(struct sys_var_with_base *variable, Item *item)
{
if (variable->var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
return set_trigger_new_row(&variable->base_name, item);
}
if (variable->var)
{
/* It is a system variable. */
return set_system_variable(variable, option_type, item);
}
/*
spcont and spv should not be NULL, as the variable
was previously checked by init_internal_variable().
*/
DBUG_ASSERT(spcont);
sp_variable *spv= spcont->find_variable(variable->base_name, false);
DBUG_ASSERT(spv);
/* It is a local variable. */
return set_local_variable(spv, item);
}
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
uint binlog_unsafe_map[256]; uint binlog_unsafe_map[256];
......
...@@ -3104,6 +3104,7 @@ struct LEX: public Query_tables_list ...@@ -3104,6 +3104,7 @@ struct LEX: public Query_tables_list
LEX_STRING dbname, LEX_STRING name); LEX_STRING dbname, LEX_STRING name);
bool init_default_internal_variable(struct sys_var_with_base *variable, bool init_default_internal_variable(struct sys_var_with_base *variable,
LEX_STRING name); LEX_STRING name);
bool set_variable(struct sys_var_with_base *variable, Item *item);
void sp_variable_declarations_init(THD *thd, int nvars); void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars, bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition &cdef, const Column_definition &cdef,
......
...@@ -14709,30 +14709,9 @@ option_value_following_option_type: ...@@ -14709,30 +14709,9 @@ option_value_following_option_type:
option_value_no_option_type: option_value_no_option_type:
internal_variable_name equal set_expr_or_default internal_variable_name equal set_expr_or_default
{ {
LEX *lex= Lex; if (Lex->set_variable(&$1, $3))
if ($1.var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
if (lex->set_trigger_new_row(&$1.base_name, $3))
MYSQL_YYABORT;
}
else if ($1.var)
{
/* It is a system variable. */
if (lex->set_system_variable(&$1, lex->option_type, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
else
{
sp_pcontext *spc= lex->spcont;
sp_variable *spv= spc->find_variable($1.base_name, false);
/* It is a local variable. */
if (lex->set_local_variable(spv, $3))
MYSQL_YYABORT;
}
}
| '@' ident_or_text equal expr | '@' ident_or_text equal expr
{ {
Item_func_set_user_var *item; Item_func_set_user_var *item;
......
...@@ -14599,26 +14599,10 @@ set_assign: ...@@ -14599,26 +14599,10 @@ set_assign:
} }
set_expr_or_default set_expr_or_default
{ {
if ($1.var == trg_new_row_fake_var) if (Lex->set_variable(&$1, $4) ||
{ sp_create_assignment_instr(thd, yychar == YYEMPTY))
/* We are in trigger and assigning value to field of new row */
if (Lex->set_trigger_new_row(&$1.base_name, $4) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
else
{
sp_pcontext *spc= Lex->spcont;
sp_variable *spv= spc->find_variable($1.base_name, false);
/* It is a local variable. */
if (Lex->set_local_variable(spv, $4))
MYSQL_YYABORT;
if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
}
; ;
set_stmt_option_value_following_option_type_list: set_stmt_option_value_following_option_type_list:
...@@ -14755,30 +14739,9 @@ option_value_following_option_type: ...@@ -14755,30 +14739,9 @@ option_value_following_option_type:
option_value_no_option_type: option_value_no_option_type:
internal_variable_name equal set_expr_or_default internal_variable_name equal set_expr_or_default
{ {
LEX *lex= Lex; if (Lex->set_variable(&$1, $3))
if ($1.var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
if (lex->set_trigger_new_row(&$1.base_name, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
else if ($1.var)
{
/* It is a system variable. */
if (lex->set_system_variable(&$1, lex->option_type, $3))
MYSQL_YYABORT;
}
else
{
sp_pcontext *spc= lex->spcont;
sp_variable *spv= spc->find_variable($1.base_name, false);
/* It is a local variable. */
if (lex->set_local_variable(spv, $3))
MYSQL_YYABORT;
}
}
| '@' ident_or_text equal expr | '@' ident_or_text equal expr
{ {
Item_func_set_user_var *item; Item_func_set_user_var *item;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment