Merge of fix for Bug#48459
This commit is contained in:
commit
fa61292476
@ -4335,7 +4335,7 @@ com_status(String *buffer __attribute__((unused)),
|
||||
Don't remove "limit 1",
|
||||
it is protection againts SQL_SELECT_LIMIT=0
|
||||
*/
|
||||
if (mysql_store_result_for_lazy(&result))
|
||||
if (!mysql_store_result_for_lazy(&result))
|
||||
{
|
||||
MYSQL_ROW cur=mysql_fetch_row(result);
|
||||
if (cur)
|
||||
@ -4379,7 +4379,7 @@ com_status(String *buffer __attribute__((unused)),
|
||||
if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR)
|
||||
return 0;
|
||||
}
|
||||
if (mysql_store_result_for_lazy(&result))
|
||||
if (!mysql_store_result_for_lazy(&result))
|
||||
{
|
||||
MYSQL_ROW cur=mysql_fetch_row(result);
|
||||
if (cur)
|
||||
|
13
mysql-test/r/bug47671.result
Normal file
13
mysql-test/r/bug47671.result
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39
|
||||
#
|
||||
# Extract only charset information from 'status' command output using regex
|
||||
--------------
|
||||
|
||||
Server characterset: utf8
|
||||
Db characterset: utf8
|
||||
Client characterset: utf8
|
||||
Conn. characterset: utf8
|
||||
|
||||
--------------
|
||||
|
@ -6979,6 +6979,64 @@ CALL p1;
|
||||
ERROR 42S22: Unknown column 'A.b' in 'IN/ALL/ANY subquery'
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug#47627: SET @@{global.session}.local_variable in stored routine causes crash
|
||||
# Bug#48626: Crash or lost connection using SET for declared variables with @@
|
||||
#
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP PROCEDURE IF EXISTS p2;
|
||||
DROP PROCEDURE IF EXISTS p3;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@SESSION.v= 10;
|
||||
END//
|
||||
ERROR HY000: Unknown system variable 'v'
|
||||
CREATE PROCEDURE p2()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET v= 10;
|
||||
END//
|
||||
call p2()//
|
||||
CREATE PROCEDURE p3()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SELECT @@SESSION.v;
|
||||
END//
|
||||
ERROR HY000: Unknown system variable 'v'
|
||||
CREATE PROCEDURE p4()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@GLOBAL.v= 10;
|
||||
END//
|
||||
ERROR HY000: Unknown system variable 'v'
|
||||
CREATE PROCEDURE p5()
|
||||
BEGIN
|
||||
DECLARE init_connect INT DEFAULT 0;
|
||||
SET init_connect= 10;
|
||||
SET @@GLOBAL.init_connect= 'SELECT 1';
|
||||
SET @@SESSION.IDENTITY= 1;
|
||||
SELECT @@SESSION.IDENTITY;
|
||||
SELECT @@GLOBAL.init_connect;
|
||||
SELECT init_connect;
|
||||
END//
|
||||
CREATE PROCEDURE p6()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@v= 0;
|
||||
END//
|
||||
ERROR HY000: Unknown system variable 'v'
|
||||
SET @old_init_connect= @@GLOBAL.init_connect;
|
||||
CALL p5();
|
||||
@@SESSION.IDENTITY
|
||||
1
|
||||
@@GLOBAL.init_connect
|
||||
SELECT 1
|
||||
init_connect
|
||||
10
|
||||
SET @@GLOBAL.init_connect= @old_init_connect;
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p5;
|
||||
# ------------------------------------------------------------------
|
||||
# -- End of 5.1 tests
|
||||
# ------------------------------------------------------------------
|
||||
|
1
mysql-test/t/bug47671-master.opt
Normal file
1
mysql-test/t/bug47671-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--default-character-set=utf8 --skip-character-set-client-handshake
|
6
mysql-test/t/bug47671.test
Normal file
6
mysql-test/t/bug47671.test
Normal file
@ -0,0 +1,6 @@
|
||||
--echo #
|
||||
--echo # Bug#47671 - wrong character-set after upgrade from 5.1.34 to 5.1.39
|
||||
--echo #
|
||||
--echo # Extract only charset information from 'status' command output using regex
|
||||
--replace_regex /.*mysql.*// /Connection.*// /Current.*// /SSL.*// /Using.*// /Server version.*// /Protocol.*// /UNIX.*// /Uptime.*// /Threads.*//
|
||||
--exec $MYSQL -u root test -e "status";
|
@ -8263,6 +8263,73 @@ CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#47627: SET @@{global.session}.local_variable in stored routine causes crash
|
||||
--echo # Bug#48626: Crash or lost connection using SET for declared variables with @@
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP PROCEDURE IF EXISTS p2;
|
||||
DROP PROCEDURE IF EXISTS p3;
|
||||
--enable_warnings
|
||||
|
||||
delimiter //;
|
||||
|
||||
--error ER_UNKNOWN_SYSTEM_VARIABLE
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@SESSION.v= 10;
|
||||
END//
|
||||
|
||||
CREATE PROCEDURE p2()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET v= 10;
|
||||
END//
|
||||
call p2()//
|
||||
|
||||
--error ER_UNKNOWN_SYSTEM_VARIABLE
|
||||
CREATE PROCEDURE p3()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SELECT @@SESSION.v;
|
||||
END//
|
||||
|
||||
--error ER_UNKNOWN_SYSTEM_VARIABLE
|
||||
CREATE PROCEDURE p4()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@GLOBAL.v= 10;
|
||||
END//
|
||||
|
||||
CREATE PROCEDURE p5()
|
||||
BEGIN
|
||||
DECLARE init_connect INT DEFAULT 0;
|
||||
SET init_connect= 10;
|
||||
SET @@GLOBAL.init_connect= 'SELECT 1';
|
||||
SET @@SESSION.IDENTITY= 1;
|
||||
SELECT @@SESSION.IDENTITY;
|
||||
SELECT @@GLOBAL.init_connect;
|
||||
SELECT init_connect;
|
||||
END//
|
||||
|
||||
--error ER_UNKNOWN_SYSTEM_VARIABLE
|
||||
CREATE PROCEDURE p6()
|
||||
BEGIN
|
||||
DECLARE v INT DEFAULT 0;
|
||||
SET @@v= 0;
|
||||
END//
|
||||
|
||||
delimiter ;//
|
||||
|
||||
SET @old_init_connect= @@GLOBAL.init_connect;
|
||||
CALL p5();
|
||||
SET @@GLOBAL.init_connect= @old_init_connect;
|
||||
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p5;
|
||||
|
||||
--echo # ------------------------------------------------------------------
|
||||
--echo # -- End of 5.1 tests
|
||||
|
@ -960,12 +960,23 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
|
||||
(*b)->field_type() == MYSQL_TYPE_YEAR))
|
||||
{
|
||||
is_nulls_eq= is_owner_equal_func();
|
||||
year_as_datetime= FALSE;
|
||||
|
||||
if ((*a)->is_datetime())
|
||||
{
|
||||
year_as_datetime= TRUE;
|
||||
get_value_a_func= &get_datetime_value;
|
||||
} else if ((*a)->field_type() == MYSQL_TYPE_YEAR)
|
||||
get_value_a_func= &get_year_value;
|
||||
else
|
||||
{
|
||||
/*
|
||||
Because convert_constant_item is called only for EXECUTE in PS mode
|
||||
the value of get_value_x_func set in PREPARE might be not
|
||||
valid for EXECUTE.
|
||||
*/
|
||||
get_value_a_func= NULL;
|
||||
}
|
||||
|
||||
if ((*b)->is_datetime())
|
||||
{
|
||||
@ -973,6 +984,8 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
|
||||
get_value_b_func= &get_datetime_value;
|
||||
} else if ((*b)->field_type() == MYSQL_TYPE_YEAR)
|
||||
get_value_b_func= &get_year_value;
|
||||
else
|
||||
get_value_b_func= NULL;
|
||||
|
||||
func= &Arg_comparator::compare_year;
|
||||
return 0;
|
||||
|
252
sql/sql_yacc.yy
252
sql/sql_yacc.yy
@ -389,6 +389,138 @@ void case_stmt_action_end_case(LEX *lex, bool simple)
|
||||
lex->sphead->do_cont_backpatch();
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
|
||||
{
|
||||
tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length);
|
||||
|
||||
if (tmp->var == NULL)
|
||||
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), tmp->base_name.str);
|
||||
else
|
||||
tmp->base_name= null_lex_str;
|
||||
|
||||
return thd->is_error();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper action for a SET statement.
|
||||
Used to push a system variable into the assignment list.
|
||||
|
||||
@param thd the current thread
|
||||
@param tmp the system variable with base name
|
||||
@param var_type the scope of the variable
|
||||
@param val the value being assigned to the variable
|
||||
|
||||
@return TRUE if error, FALSE otherwise.
|
||||
*/
|
||||
|
||||
static bool
|
||||
set_system_variable(THD *thd, struct sys_var_with_base *tmp,
|
||||
enum enum_var_type var_type, Item *val)
|
||||
{
|
||||
set_var *var;
|
||||
LEX *lex= thd->lex;
|
||||
|
||||
/* No AUTOCOMMIT from a stored function or trigger. */
|
||||
if (lex->spcont && tmp->var == &sys_autocommit)
|
||||
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
|
||||
|
||||
if (! (var= new set_var(var_type, tmp->var, &tmp->base_name, val)))
|
||||
return TRUE;
|
||||
|
||||
return lex->var_list.push_back(var);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper action for a SET statement.
|
||||
Used to push a SP local variable into the assignment list.
|
||||
|
||||
@param thd the current thread
|
||||
@param var_type the SP local variable
|
||||
@param val the value being assigned to the variable
|
||||
|
||||
@return TRUE if error, FALSE otherwise.
|
||||
*/
|
||||
|
||||
static bool
|
||||
set_local_variable(THD *thd, sp_variable_t *spv, Item *val)
|
||||
{
|
||||
Item *it;
|
||||
LEX *lex= thd->lex;
|
||||
sp_instr_set *sp_set;
|
||||
|
||||
if (val)
|
||||
it= val;
|
||||
else if (spv->dflt)
|
||||
it= spv->dflt;
|
||||
else
|
||||
{
|
||||
it= new (thd->mem_root) Item_null();
|
||||
if (it == NULL)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sp_set= new sp_instr_set(lex->sphead->instructions(), lex->spcont,
|
||||
spv->offset, it, spv->type, lex, TRUE);
|
||||
|
||||
return (sp_set == NULL || lex->sphead->add_instr(sp_set));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper action for a SET statement.
|
||||
Used to SET a field of NEW row.
|
||||
|
||||
@param thd the current thread
|
||||
@param name the field name
|
||||
@param val the value being assigned to the row
|
||||
|
||||
@return TRUE if error, FALSE otherwise.
|
||||
*/
|
||||
|
||||
static bool
|
||||
set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
Item_trigger_field *trg_fld;
|
||||
sp_instr_set_trigger_field *sp_fld;
|
||||
|
||||
/* QQ: Shouldn't this be field's default value ? */
|
||||
if (! val)
|
||||
val= new Item_null();
|
||||
|
||||
DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
|
||||
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
|
||||
lex->trg_chistics.event == TRG_EVENT_UPDATE));
|
||||
|
||||
trg_fld= new (thd->mem_root)
|
||||
Item_trigger_field(lex->current_context(),
|
||||
Item_trigger_field::NEW_ROW,
|
||||
name->str, UPDATE_ACL, FALSE);
|
||||
|
||||
if (trg_fld == NULL)
|
||||
return TRUE;
|
||||
|
||||
sp_fld= new sp_instr_set_trigger_field(lex->sphead->instructions(),
|
||||
lex->spcont, trg_fld, val, lex);
|
||||
|
||||
if (sp_fld == NULL)
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
Let us add this item to list of all Item_trigger_field
|
||||
objects in trigger.
|
||||
*/
|
||||
lex->trg_table_fields.link_in_list((uchar *) trg_fld,
|
||||
(uchar **) &trg_fld->next_trg_field);
|
||||
|
||||
return lex->sphead->add_instr(sp_fld);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
|
||||
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
|
||||
@ -11830,98 +11962,42 @@ sys_option_value:
|
||||
option_type internal_variable_name equal set_expr_or_default
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex=Lex;
|
||||
LEX *lex= Lex;
|
||||
LEX_STRING *name= &$2.base_name;
|
||||
|
||||
if ($2.var == trg_new_row_fake_var)
|
||||
{
|
||||
/* We are in trigger and assigning value to field of new row */
|
||||
Item *it;
|
||||
Item_trigger_field *trg_fld;
|
||||
sp_instr_set_trigger_field *sp_fld;
|
||||
LINT_INIT(sp_fld);
|
||||
if ($1)
|
||||
{
|
||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
if ($4)
|
||||
it= $4;
|
||||
else
|
||||
{
|
||||
/* QQ: Shouldn't this be field's default value ? */
|
||||
it= new Item_null();
|
||||
}
|
||||
|
||||
DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
|
||||
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
|
||||
lex->trg_chistics.event == TRG_EVENT_UPDATE));
|
||||
|
||||
trg_fld= new (thd->mem_root)
|
||||
Item_trigger_field(Lex->current_context(),
|
||||
Item_trigger_field::NEW_ROW,
|
||||
$2.base_name.str,
|
||||
UPDATE_ACL, FALSE);
|
||||
if (trg_fld == NULL)
|
||||
MYSQL_YYABORT;
|
||||
|
||||
sp_fld= new sp_instr_set_trigger_field(lex->sphead->
|
||||
instructions(),
|
||||
lex->spcont,
|
||||
trg_fld,
|
||||
it, lex);
|
||||
if (sp_fld == NULL)
|
||||
MYSQL_YYABORT;
|
||||
|
||||
/*
|
||||
Let us add this item to list of all Item_trigger_field
|
||||
objects in trigger.
|
||||
*/
|
||||
lex->trg_table_fields.link_in_list((uchar *)trg_fld,
|
||||
(uchar **) &trg_fld->
|
||||
next_trg_field);
|
||||
|
||||
if (lex->sphead->add_instr(sp_fld))
|
||||
if (set_trigger_new_row(YYTHD, name, $4))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
else if ($2.var)
|
||||
{ /* System variable */
|
||||
{
|
||||
if ($1)
|
||||
lex->option_type= $1;
|
||||
set_var *var= new set_var(lex->option_type, $2.var,
|
||||
&$2.base_name, $4);
|
||||
if (var == NULL)
|
||||
|
||||
/* It is a system variable. */
|
||||
if (set_system_variable(thd, &$2, lex->option_type, $4))
|
||||
MYSQL_YYABORT;
|
||||
lex->var_list.push_back(var);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An SP local variable */
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
sp_variable_t *spv;
|
||||
sp_instr_set *sp_set;
|
||||
Item *it;
|
||||
sp_pcontext *spc= lex->spcont;
|
||||
sp_variable_t *spv= spc->find_variable(name);
|
||||
|
||||
if ($1)
|
||||
{
|
||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
|
||||
spv= ctx->find_variable(&$2.base_name);
|
||||
|
||||
if ($4)
|
||||
it= $4;
|
||||
else if (spv->dflt)
|
||||
it= spv->dflt;
|
||||
else
|
||||
{
|
||||
it= new (thd->mem_root) Item_null();
|
||||
if (it == NULL)
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
|
||||
spv->offset, it, spv->type, lex, TRUE);
|
||||
if (sp_set == NULL ||
|
||||
lex->sphead->add_instr(sp_set))
|
||||
/* It is a local variable. */
|
||||
if (set_local_variable(thd, spv, $4))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
}
|
||||
@ -11957,11 +12033,16 @@ option_value:
|
||||
}
|
||||
| '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
set_var *var= new set_var($3, $4.var, &$4.base_name, $6);
|
||||
if (var == NULL)
|
||||
THD *thd= YYTHD;
|
||||
struct sys_var_with_base tmp= $4;
|
||||
/* Lookup if necessary: must be a system variable. */
|
||||
if (tmp.var == NULL)
|
||||
{
|
||||
if (find_sys_var_null_base(thd, &tmp))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
if (set_system_variable(thd, &tmp, $3, $6))
|
||||
MYSQL_YYABORT;
|
||||
lex->var_list.push_back(var);
|
||||
}
|
||||
| charset old_or_new_charset_name_or_default
|
||||
{
|
||||
@ -12054,31 +12135,26 @@ internal_variable_name:
|
||||
ident
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
sp_pcontext *spc= lex->spcont;
|
||||
sp_pcontext *spc= thd->lex->spcont;
|
||||
sp_variable_t *spv;
|
||||
|
||||
/* We have to lookup here since local vars can shadow sysvars */
|
||||
/* Best effort lookup for system variable. */
|
||||
if (!spc || !(spv = spc->find_variable(&$1)))
|
||||
{
|
||||
struct sys_var_with_base tmp= {NULL, $1};
|
||||
|
||||
/* Not an SP local variable */
|
||||
sys_var *tmp=find_sys_var(thd, $1.str, $1.length);
|
||||
if (!tmp)
|
||||
if (find_sys_var_null_base(thd, &tmp))
|
||||
MYSQL_YYABORT;
|
||||
$$.var= tmp;
|
||||
$$.base_name= null_lex_str;
|
||||
if (spc && tmp == &sys_autocommit)
|
||||
{
|
||||
/*
|
||||
We don't allow setting AUTOCOMMIT from a stored function
|
||||
or trigger.
|
||||
*/
|
||||
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
|
||||
}
|
||||
|
||||
$$= tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An SP local variable */
|
||||
/*
|
||||
Possibly an SP local variable (or a shadowed sysvar).
|
||||
Will depend on the context of the SET statement.
|
||||
*/
|
||||
$$.var= NULL;
|
||||
$$.base_name= $1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user