mirror of
https://github.com/MariaDB/server.git
synced 2025-07-14 13:41:20 +03:00
A fix and a test case for Bug#15441 "Running SP causes Server
to Crash": the bug was that due to non-standard name resolution precedence in stored procedures (See Bug#5967) a stored procedure variable took precedence over a table column when the arguments for VALUES() function were resolved. The implementation of VALUES() function was not designed to work with Item_splocal and crashed. VALUES() function is non-standard. It can refer to, and is meaningful for, table columns only. The patch disables SP variables as possible arguments of VALUES() function.
This commit is contained in:
@ -4110,23 +4110,23 @@ call bug14376(4711)|
|
|||||||
x
|
x
|
||||||
4711
|
4711
|
||||||
drop procedure bug14376|
|
drop procedure bug14376|
|
||||||
drop procedure if exists p1|
|
drop procedure if exists bug5967|
|
||||||
drop table if exists t1|
|
drop table if exists t3|
|
||||||
create table t1 (a varchar(255))|
|
create table t3 (a varchar(255))|
|
||||||
insert into t1 (a) values ("a - table column")|
|
insert into t3 (a) values ("a - table column")|
|
||||||
create procedure p1(a varchar(255))
|
create procedure bug5967(a varchar(255))
|
||||||
begin
|
begin
|
||||||
declare i varchar(255);
|
declare i varchar(255);
|
||||||
declare c cursor for select a from t1;
|
declare c cursor for select a from t3;
|
||||||
select a;
|
select a;
|
||||||
select a from t1 into i;
|
select a from t3 into i;
|
||||||
select i as 'Parameter takes precedence over table column'; open c;
|
select i as 'Parameter takes precedence over table column'; open c;
|
||||||
fetch c into i;
|
fetch c into i;
|
||||||
close c;
|
close c;
|
||||||
select i as 'Parameter takes precedence over table column in cursors';
|
select i as 'Parameter takes precedence over table column in cursors';
|
||||||
begin
|
begin
|
||||||
declare a varchar(255) default 'a - local variable';
|
declare a varchar(255) default 'a - local variable';
|
||||||
declare c1 cursor for select a from t1;
|
declare c1 cursor for select a from t3;
|
||||||
select a as 'A local variable takes precedence over parameter';
|
select a as 'A local variable takes precedence over parameter';
|
||||||
open c1;
|
open c1;
|
||||||
fetch c1 into i;
|
fetch c1 into i;
|
||||||
@ -4134,9 +4134,9 @@ close c1;
|
|||||||
select i as 'A local variable takes precedence over parameter in cursors';
|
select i as 'A local variable takes precedence over parameter in cursors';
|
||||||
begin
|
begin
|
||||||
declare a varchar(255) default 'a - local variable in a nested compound statement';
|
declare a varchar(255) default 'a - local variable in a nested compound statement';
|
||||||
declare c2 cursor for select a from t1;
|
declare c2 cursor for select a from t3;
|
||||||
select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement';
|
select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement';
|
||||||
select a from t1 into i;
|
select a from t3 into i;
|
||||||
select i as 'A local variable in a nested compound statement takes precedence over table column';
|
select i as 'A local variable in a nested compound statement takes precedence over table column';
|
||||||
open c2;
|
open c2;
|
||||||
fetch c2 into i;
|
fetch c2 into i;
|
||||||
@ -4145,7 +4145,7 @@ select i as 'A local variable in a nested compound statement takes precedence o
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end|
|
end|
|
||||||
call p1("a - stored procedure parameter")|
|
call bug5967("a - stored procedure parameter")|
|
||||||
a
|
a
|
||||||
a - stored procedure parameter
|
a - stored procedure parameter
|
||||||
Parameter takes precedence over table column
|
Parameter takes precedence over table column
|
||||||
@ -4162,7 +4162,7 @@ A local variable in a nested compound statement takes precedence over table colu
|
|||||||
a - local variable in a nested compound statement
|
a - local variable in a nested compound statement
|
||||||
A local variable in a nested compound statement takes precedence over table column in cursors
|
A local variable in a nested compound statement takes precedence over table column in cursors
|
||||||
a - local variable in a nested compound statement
|
a - local variable in a nested compound statement
|
||||||
drop procedure p1|
|
drop procedure bug5967|
|
||||||
drop procedure if exists bug13012|
|
drop procedure if exists bug13012|
|
||||||
create procedure bug13012()
|
create procedure bug13012()
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -4190,17 +4190,17 @@ call bug13012()|
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair status OK
|
test.t1 repair status OK
|
||||||
test.t2 repair status OK
|
test.t2 repair status OK
|
||||||
test.t3 repair error Table 'test.t3' doesn't exist
|
test.t3 repair status OK
|
||||||
test.v1 repair error 'test.v1' is not BASE TABLE
|
test.v1 repair error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize status OK
|
test.t1 optimize status OK
|
||||||
test.t2 optimize status OK
|
test.t2 optimize status OK
|
||||||
test.t3 optimize error Table 'test.t3' doesn't exist
|
test.t3 optimize status OK
|
||||||
test.v1 optimize error 'test.v1' is not BASE TABLE
|
test.v1 optimize error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 analyze status Table is already up to date
|
test.t1 analyze status Table is already up to date
|
||||||
test.t2 analyze status Table is already up to date
|
test.t2 analyze status Table is already up to date
|
||||||
test.t3 analyze error Table 'test.t3' doesn't exist
|
test.t3 analyze status Table is already up to date
|
||||||
test.v1 analyze error 'test.v1' is not BASE TABLE
|
test.v1 analyze error 'test.v1' is not BASE TABLE
|
||||||
Warnings:
|
Warnings:
|
||||||
Error 1347 'test.v1' is not BASE TABLE
|
Error 1347 'test.v1' is not BASE TABLE
|
||||||
@ -4208,17 +4208,17 @@ call bug13012()|
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair status OK
|
test.t1 repair status OK
|
||||||
test.t2 repair status OK
|
test.t2 repair status OK
|
||||||
test.t3 repair error Table 'test.t3' doesn't exist
|
test.t3 repair status OK
|
||||||
test.v1 repair error 'test.v1' is not BASE TABLE
|
test.v1 repair error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize status OK
|
test.t1 optimize status OK
|
||||||
test.t2 optimize status OK
|
test.t2 optimize status OK
|
||||||
test.t3 optimize error Table 'test.t3' doesn't exist
|
test.t3 optimize status OK
|
||||||
test.v1 optimize error 'test.v1' is not BASE TABLE
|
test.v1 optimize error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 analyze status Table is already up to date
|
test.t1 analyze status Table is already up to date
|
||||||
test.t2 analyze status Table is already up to date
|
test.t2 analyze status Table is already up to date
|
||||||
test.t3 analyze error Table 'test.t3' doesn't exist
|
test.t3 analyze status Table is already up to date
|
||||||
test.v1 analyze error 'test.v1' is not BASE TABLE
|
test.v1 analyze error 'test.v1' is not BASE TABLE
|
||||||
Warnings:
|
Warnings:
|
||||||
Error 1347 'test.v1' is not BASE TABLE
|
Error 1347 'test.v1' is not BASE TABLE
|
||||||
@ -4226,25 +4226,34 @@ call bug13012()|
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 repair status OK
|
test.t1 repair status OK
|
||||||
test.t2 repair status OK
|
test.t2 repair status OK
|
||||||
test.t3 repair error Table 'test.t3' doesn't exist
|
test.t3 repair status OK
|
||||||
test.v1 repair error 'test.v1' is not BASE TABLE
|
test.v1 repair error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 optimize status OK
|
test.t1 optimize status OK
|
||||||
test.t2 optimize status OK
|
test.t2 optimize status OK
|
||||||
test.t3 optimize error Table 'test.t3' doesn't exist
|
test.t3 optimize status OK
|
||||||
test.v1 optimize error 'test.v1' is not BASE TABLE
|
test.v1 optimize error 'test.v1' is not BASE TABLE
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 analyze status Table is already up to date
|
test.t1 analyze status Table is already up to date
|
||||||
test.t2 analyze status Table is already up to date
|
test.t2 analyze status Table is already up to date
|
||||||
test.t3 analyze error Table 'test.t3' doesn't exist
|
test.t3 analyze status Table is already up to date
|
||||||
test.v1 analyze error 'test.v1' is not BASE TABLE
|
test.v1 analyze error 'test.v1' is not BASE TABLE
|
||||||
Warnings:
|
Warnings:
|
||||||
Error 1347 'test.v1' is not BASE TABLE
|
Error 1347 'test.v1' is not BASE TABLE
|
||||||
drop procedure bug13012|
|
drop procedure bug13012|
|
||||||
drop view v1;
|
drop view v1;
|
||||||
select * from t1|
|
select * from t1|
|
||||||
a
|
id data
|
||||||
a - table column
|
aa 0
|
||||||
|
aa 1
|
||||||
|
aa 2
|
||||||
|
aa 3
|
||||||
|
aa 4
|
||||||
|
aa 5
|
||||||
|
aa 6
|
||||||
|
aa 7
|
||||||
|
aa 8
|
||||||
|
aa 9
|
||||||
drop schema if exists mysqltest1|
|
drop schema if exists mysqltest1|
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1008 Can't drop database 'mysqltest1'; database doesn't exist
|
Note 1008 Can't drop database 'mysqltest1'; database doesn't exist
|
||||||
@ -4284,4 +4293,31 @@ drop schema if exists mysqltest1|
|
|||||||
drop schema if exists mysqltest2|
|
drop schema if exists mysqltest2|
|
||||||
drop schema if exists mysqltest3|
|
drop schema if exists mysqltest3|
|
||||||
use test|
|
use test|
|
||||||
|
drop table if exists t3|
|
||||||
|
drop procedure if exists bug15441|
|
||||||
|
create table t3 (id int not null primary key, county varchar(25))|
|
||||||
|
insert into t3 (id, county) values (1, 'York')|
|
||||||
|
create procedure bug15441(c varchar(25))
|
||||||
|
begin
|
||||||
|
update t3 set id=2, county=values(c);
|
||||||
|
end|
|
||||||
|
call bug15441('county')|
|
||||||
|
ERROR 42S22: Unknown column 'c' in 'field list'
|
||||||
|
drop procedure bug15441|
|
||||||
|
create procedure bug15441(county varchar(25))
|
||||||
|
begin
|
||||||
|
declare c varchar(25) default "hello";
|
||||||
|
insert into t3 (id, county) values (1, county)
|
||||||
|
on duplicate key update county= values(county);
|
||||||
|
select * from t3;
|
||||||
|
update t3 set id=2, county=values(id);
|
||||||
|
select * from t3;
|
||||||
|
end|
|
||||||
|
call bug15441('Yale')|
|
||||||
|
id county
|
||||||
|
1 Yale
|
||||||
|
id county
|
||||||
|
2 NULL
|
||||||
|
drop table t3|
|
||||||
|
drop procedure bug15441|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
@ -4914,24 +4914,24 @@ drop procedure bug14376|
|
|||||||
#
|
#
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop procedure if exists p1|
|
drop procedure if exists bug5967|
|
||||||
drop table if exists t1|
|
drop table if exists t3|
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
create table t1 (a varchar(255))|
|
create table t3 (a varchar(255))|
|
||||||
insert into t1 (a) values ("a - table column")|
|
insert into t3 (a) values ("a - table column")|
|
||||||
create procedure p1(a varchar(255))
|
create procedure bug5967(a varchar(255))
|
||||||
begin
|
begin
|
||||||
declare i varchar(255);
|
declare i varchar(255);
|
||||||
declare c cursor for select a from t1;
|
declare c cursor for select a from t3;
|
||||||
select a;
|
select a;
|
||||||
select a from t1 into i;
|
select a from t3 into i;
|
||||||
select i as 'Parameter takes precedence over table column'; open c;
|
select i as 'Parameter takes precedence over table column'; open c;
|
||||||
fetch c into i;
|
fetch c into i;
|
||||||
close c;
|
close c;
|
||||||
select i as 'Parameter takes precedence over table column in cursors';
|
select i as 'Parameter takes precedence over table column in cursors';
|
||||||
begin
|
begin
|
||||||
declare a varchar(255) default 'a - local variable';
|
declare a varchar(255) default 'a - local variable';
|
||||||
declare c1 cursor for select a from t1;
|
declare c1 cursor for select a from t3;
|
||||||
select a as 'A local variable takes precedence over parameter';
|
select a as 'A local variable takes precedence over parameter';
|
||||||
open c1;
|
open c1;
|
||||||
fetch c1 into i;
|
fetch c1 into i;
|
||||||
@ -4939,9 +4939,9 @@ begin
|
|||||||
select i as 'A local variable takes precedence over parameter in cursors';
|
select i as 'A local variable takes precedence over parameter in cursors';
|
||||||
begin
|
begin
|
||||||
declare a varchar(255) default 'a - local variable in a nested compound statement';
|
declare a varchar(255) default 'a - local variable in a nested compound statement';
|
||||||
declare c2 cursor for select a from t1;
|
declare c2 cursor for select a from t3;
|
||||||
select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement';
|
select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement';
|
||||||
select a from t1 into i;
|
select a from t3 into i;
|
||||||
select i as 'A local variable in a nested compound statement takes precedence over table column';
|
select i as 'A local variable in a nested compound statement takes precedence over table column';
|
||||||
open c2;
|
open c2;
|
||||||
fetch c2 into i;
|
fetch c2 into i;
|
||||||
@ -4950,8 +4950,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end|
|
end|
|
||||||
call p1("a - stored procedure parameter")|
|
call bug5967("a - stored procedure parameter")|
|
||||||
drop procedure p1|
|
drop procedure bug5967|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server"
|
# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server"
|
||||||
@ -5028,6 +5028,56 @@ drop schema if exists mysqltest2|
|
|||||||
drop schema if exists mysqltest3|
|
drop schema if exists mysqltest3|
|
||||||
use test|
|
use test|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#15441 "Running SP causes Server to Crash": check that an SP variable
|
||||||
|
# can not be used in VALUES() function.
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t3|
|
||||||
|
drop procedure if exists bug15441|
|
||||||
|
--enable_warnings
|
||||||
|
create table t3 (id int not null primary key, county varchar(25))|
|
||||||
|
insert into t3 (id, county) values (1, 'York')|
|
||||||
|
|
||||||
|
# First check that a stored procedure that refers to a parameter in VALUES()
|
||||||
|
# function won't parse.
|
||||||
|
|
||||||
|
create procedure bug15441(c varchar(25))
|
||||||
|
begin
|
||||||
|
update t3 set id=2, county=values(c);
|
||||||
|
end|
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
call bug15441('county')|
|
||||||
|
drop procedure bug15441|
|
||||||
|
|
||||||
|
# Now check the case when there is an ambiguity between column names
|
||||||
|
# and stored procedure parameters: the parser shall resolve the argument
|
||||||
|
# of VALUES() function to the column name.
|
||||||
|
|
||||||
|
# It's hard to deduce what county refers to in every case (INSERT statement):
|
||||||
|
# 1st county refers to the column
|
||||||
|
# 2nd county refers to the procedure parameter
|
||||||
|
# 3d and 4th county refers to the column, again, but
|
||||||
|
# for 4th county it has the value of SP parameter
|
||||||
|
|
||||||
|
# In UPDATE statement, just check that values() function returns NULL for
|
||||||
|
# non- INSERT...UPDATE statements, as stated in the manual.
|
||||||
|
|
||||||
|
create procedure bug15441(county varchar(25))
|
||||||
|
begin
|
||||||
|
declare c varchar(25) default "hello";
|
||||||
|
|
||||||
|
insert into t3 (id, county) values (1, county)
|
||||||
|
on duplicate key update county= values(county);
|
||||||
|
select * from t3;
|
||||||
|
|
||||||
|
update t3 set id=2, county=values(id);
|
||||||
|
select * from t3;
|
||||||
|
end|
|
||||||
|
call bug15441('Yale')|
|
||||||
|
drop table t3|
|
||||||
|
drop procedure bug15441|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
|
@ -5148,10 +5148,17 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
|
|||||||
Item_ref *ref= (Item_ref *)arg;
|
Item_ref *ref= (Item_ref *)arg;
|
||||||
if (ref->ref[0]->type() != FIELD_ITEM)
|
if (ref->ref[0]->type() != FIELD_ITEM)
|
||||||
{
|
{
|
||||||
|
my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
arg= ref->ref[0];
|
arg= ref->ref[0];
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
According to our SQL grammar, VALUES() function can reference
|
||||||
|
only to a column.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(arg->type() == FIELD_ITEM);
|
||||||
|
|
||||||
Item_field *field_arg= (Item_field *)arg;
|
Item_field *field_arg= (Item_field *)arg;
|
||||||
|
|
||||||
if (field_arg->field->table->insert_values)
|
if (field_arg->field->table->insert_values)
|
||||||
|
10
sql/item.h
10
sql/item.h
@ -2056,6 +2056,16 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Item_insert_value -- an implementation of VALUES() function.
|
||||||
|
You can use the VALUES(col_name) function in the UPDATE clause
|
||||||
|
to refer to column values from the INSERT portion of the INSERT
|
||||||
|
... UPDATE statement. In other words, VALUES(col_name) in the
|
||||||
|
UPDATE clause refers to the value of col_name that would be
|
||||||
|
inserted, had no duplicate-key conflict occurred.
|
||||||
|
In all other places this function returns NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
class Item_insert_value : public Item_field
|
class Item_insert_value : public Item_field
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -4438,7 +4438,7 @@ simple_expr:
|
|||||||
}
|
}
|
||||||
$$= new Item_default_value(Lex->current_context(), $3);
|
$$= new Item_default_value(Lex->current_context(), $3);
|
||||||
}
|
}
|
||||||
| VALUES '(' simple_ident ')'
|
| VALUES '(' simple_ident_nospvar ')'
|
||||||
{ $$= new Item_insert_value(Lex->current_context(), $3); }
|
{ $$= new Item_insert_value(Lex->current_context(), $3); }
|
||||||
| FUNC_ARG0 '(' ')'
|
| FUNC_ARG0 '(' ')'
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user