summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-12-09 00:58:59 +0300
committerunknown <konstantin@mysql.com>2005-12-09 00:58:59 +0300
commit9c4985de772e16cd8d5e7d01115ed4f994e86401 (patch)
treeba6b4e868b2afedf9235f716d384c39ef41f4edf
parent4d87cf984dde6ca1ae91375375481dfada3d0c85 (diff)
downloadmariadb-git-9c4985de772e16cd8d5e7d01115ed4f994e86401.tar.gz
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. mysql-test/r/sp.result: Test results fixed (Bug#15441). Also make sure that the recently added test cases follow sp.test internal tests standard. mysql-test/t/sp.test: Add a test case for Bug#15441 "Running SP causes Server to Crash". sql/item.cc: Cleanup Item_insert_value::fix_fields(). sql/item.h: Add a comment for Item_insert_value. sql/sql_yacc.yy: Actual fix for Bug#15441 "Running SP causes Server to Crash": we should not allow VALUES() function to reference SP variables.
-rw-r--r--mysql-test/r/sp.result82
-rw-r--r--mysql-test/t/sp.test74
-rw-r--r--sql/item.cc7
-rw-r--r--sql/item.h10
-rw-r--r--sql/sql_yacc.yy2
5 files changed, 139 insertions, 36 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 2725c42ccbe..ded9754f172 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4110,23 +4110,23 @@ call bug14376(4711)|
x
4711
drop procedure bug14376|
-drop procedure if exists p1|
-drop table if exists t1|
-create table t1 (a varchar(255))|
-insert into t1 (a) values ("a - table column")|
-create procedure p1(a varchar(255))
+drop procedure if exists bug5967|
+drop table if exists t3|
+create table t3 (a varchar(255))|
+insert into t3 (a) values ("a - table column")|
+create procedure bug5967(a varchar(255))
begin
declare i varchar(255);
-declare c cursor for select a from t1;
+declare c cursor for select a from t3;
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;
fetch c into i;
close c;
select i as 'Parameter takes precedence over table column in cursors';
begin
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';
open c1;
fetch c1 into i;
@@ -4134,9 +4134,9 @@ close c1;
select i as 'A local variable takes precedence over parameter in cursors';
begin
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 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';
open c2;
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|
-call p1("a - stored procedure parameter")|
+call bug5967("a - stored procedure parameter")|
a
a - stored procedure parameter
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 takes precedence over table column in cursors
a - local variable in a nested compound statement
-drop procedure p1|
+drop procedure bug5967|
drop procedure if exists bug13012|
create procedure bug13012()
BEGIN
@@ -4190,17 +4190,17 @@ call bug13012()|
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Warnings:
Error 1347 'test.v1' is not BASE TABLE
@@ -4208,17 +4208,17 @@ call bug13012()|
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Warnings:
Error 1347 'test.v1' is not BASE TABLE
@@ -4226,25 +4226,34 @@ call bug13012()|
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Table Op Msg_type Msg_text
test.t1 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
Warnings:
Error 1347 'test.v1' is not BASE TABLE
drop procedure bug13012|
drop view v1;
select * from t1|
-a
-a - table column
+id data
+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|
Warnings:
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 mysqltest3|
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;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index f8b638da59d..f73288f04ba 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4914,24 +4914,24 @@ drop procedure bug14376|
#
--disable_warnings
-drop procedure if exists p1|
-drop table if exists t1|
+drop procedure if exists bug5967|
+drop table if exists t3|
--enable_warnings
-create table t1 (a varchar(255))|
-insert into t1 (a) values ("a - table column")|
-create procedure p1(a varchar(255))
+create table t3 (a varchar(255))|
+insert into t3 (a) values ("a - table column")|
+create procedure bug5967(a varchar(255))
begin
declare i varchar(255);
- declare c cursor for select a from t1;
+ declare c cursor for select a from t3;
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;
fetch c into i;
close c;
select i as 'Parameter takes precedence over table column in cursors';
begin
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';
open c1;
fetch c1 into i;
@@ -4939,9 +4939,9 @@ begin
select i as 'A local variable takes precedence over parameter in cursors';
begin
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 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';
open c2;
fetch c2 into i;
@@ -4950,8 +4950,8 @@ begin
end;
end;
end|
-call p1("a - stored procedure parameter")|
-drop procedure p1|
+call bug5967("a - stored procedure parameter")|
+drop procedure bug5967|
#
# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server"
@@ -5029,6 +5029,56 @@ drop schema if exists mysqltest3|
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
#
#--disable_warnings
diff --git a/sql/item.cc b/sql/item.cc
index 3721528672a..7d2b19b87c6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5148,10 +5148,17 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
Item_ref *ref= (Item_ref *)arg;
if (ref->ref[0]->type() != FIELD_ITEM)
{
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function");
return TRUE;
}
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;
if (field_arg->field->table->insert_values)
diff --git a/sql/item.h b/sql/item.h
index 900442a45e9..9eb2e6dee88 100644
--- a/sql/item.h
+++ b/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
{
public:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 10ba5e8b271..ea948e73a2a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4438,7 +4438,7 @@ simple_expr:
}
$$= new Item_default_value(Lex->current_context(), $3);
}
- | VALUES '(' simple_ident ')'
+ | VALUES '(' simple_ident_nospvar ')'
{ $$= new Item_insert_value(Lex->current_context(), $3); }
| FUNC_ARG0 '(' ')'
{