From cc7a75e6fdf5f4253c550ee3d5d93c46b96f5678 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Mar 2006 16:19:57 +0300 Subject: [PATCH 01/11] Fixed bug#17726: Not checked empty list caused endless loop When the Item_cond::fix_fields() function reduces cond tree, it in loop scans it's own list and when it founds Item_cond with same function (AND or OR) it does next things: 1) replaces that item with item's list. 2) empties item's list. Due to this operation is done twice - for update and for view, at the update phase cond's list of lower view is already empty. Empty list returns ref to itself, thus making endless loop by replacing list with itself, emptying, replacing again and so on. This results in server hung up. To the Item_cond::fix_fields() function added check that ensures that list being replaced with isn't empty. mysql-test/t/view.test: Added test for bug#17726: Not checked empty list caused endless loop mysql-test/r/view.result: Added test for bug#17726: Not checked empty list caused endless loop sql/item_cmpfunc.cc: Fixed bug#17726: Not checked empty list caused endless loop To the Item_cond::fix_fields() function added check that ensures that list being replaced with isn't empty. --- mysql-test/r/view.result | 14 ++++++++++++++ mysql-test/t/view.test | 14 ++++++++++++++ sql/item_cmpfunc.cc | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c9a79e50cc3..7678c70bda2 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2539,3 +2539,17 @@ drop view v1; // View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache `test`.`t1`.`id` AS `id` from `t1` +create table t1(f1 int, f2 int); +create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb +.f1 and ta.f2=tb.f2; +insert into t1 values(1,1),(2,2); +create view v2 as select * from v1 where a > 1 with check option; +select * from v2; +a b +2 2 +update v2 set b=3 where a=2; +select * from v2; +a b +3 3 +drop view v2, v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index b7e678c6f77..e17e2b98527 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2385,3 +2385,17 @@ show create view v1; drop view v1; // delimiter ;// + +# +# Bug#17726 Not checked empty list caused endless loop +# +create table t1(f1 int, f2 int); +create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb +.f1 and ta.f2=tb.f2; +insert into t1 values(1,1),(2,2); +create view v2 as select * from v1 where a > 1 with check option; +select * from v2; +update v2 set b=3 where a=2; +select * from v2; +drop view v2, v1; +drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7ba8a536ac7..4cd460cfeb0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2553,7 +2553,8 @@ Item_cond::fix_fields(THD *thd, Item **ref) { table_map tmp_table_map; while (item->type() == Item::COND_ITEM && - ((Item_cond*) item)->functype() == functype()) + ((Item_cond*) item)->functype() == functype() && + !((Item_cond*) item)->list.is_empty()) { // Identical function li.replace(((Item_cond*) item)->list); ((Item_cond*) item)->list.empty(); From fb71f423c4053f108048d463df64094aef32c7bc Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Mar 2006 23:04:48 +0300 Subject: [PATCH 02/11] Undo the patch for Bug#16144 "mysql_stmt_attr_get type error", it breaks binary compatibility. The patch will be left intact in 5.1. Warning: this changeset should be null-merged into 5.1. A separate commit in order to push into the release clone of 5.0.19. libmysql/libmysql.c: Undo the patch for Bug#16144 tests/mysql_client_test.c: Undo the patch for Bug#16144 --- libmysql/libmysql.c | 2 +- tests/mysql_client_test.c | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 99f173aa153..323ddfca36f 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2822,7 +2822,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(my_bool*) value= stmt->update_max_length; + *(unsigned long *) value= stmt->update_max_length; break; case STMT_ATTR_CURSOR_TYPE: *(ulong*) value= stmt->flags; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 97511986f25..b1ea5f8ea06 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -14758,24 +14758,6 @@ static void test_bug16143() } -/* Bug #16144: mysql_stmt_attr_get type error */ - -static void test_bug16144() -{ - const my_bool flag_orig= (my_bool) 0xde; - my_bool flag= flag_orig; - MYSQL_STMT *stmt; - myheader("test_bug16144"); - - /* Check that attr_get returns correct data on little and big endian CPUs */ - stmt= mysql_stmt_init(mysql); - mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag); - mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag); - DIE_UNLESS(flag == flag_orig); - - mysql_stmt_close(stmt); -} - /* Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong field length" @@ -15137,7 +15119,6 @@ static struct my_tests_st my_tests[]= { { "test_opt_reconnect", test_opt_reconnect }, { "test_bug12744", test_bug12744 }, { "test_bug16143", test_bug16143 }, - { "test_bug16144", test_bug16144 }, { "test_bug15613", test_bug15613 }, { "test_bug14169", test_bug14169 }, { 0, 0 } From 2acff5c36d99b9726b152bcf8b5286fb46849d88 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Mar 2006 12:08:23 +0100 Subject: [PATCH 03/11] Bug#10656 Stored Procedure - Create index and Truncate table command error -Add test case Move testcase that needs innodb from sp.test => sp_trans.test mysql-test/r/sp.result: Move test cases tyhat requires innodb to sp_trans.test mysql-test/r/sp_trans.result: Move test cases tyhat requires innodb to sp_trans.test Add test case for bug#10656 mysql-test/t/sp.test: Move test cases tyhat requires innodb to sp_trans.test mysql-test/t/sp_trans.test: Add test case for bug#10656 Move test cases that require innodb to sp_trans.test --- mysql-test/r/sp.result | 71 ------------------- mysql-test/r/sp_trans.result | 105 +++++++++++++++++++++++++++ mysql-test/t/sp.test | 86 ---------------------- mysql-test/t/sp_trans.test | 134 +++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+), 157 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index a4c920f8e15..911048d1b2d 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2197,35 +2197,6 @@ select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time| 2 01-01-1970 03:16:40 drop procedure bug3426| create table t3 ( -a int primary key, -ach char(1) -) engine = innodb| -create table t4 ( -b int primary key , -bch char(1) -) engine = innodb| -insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')| -Warnings: -Warning 1265 Data truncated for column 'ach' at row 1 -Warning 1265 Data truncated for column 'ach' at row 2 -insert into t4 values (1 , 'bCh1' )| -Warnings: -Warning 1265 Data truncated for column 'bch' at row 1 -drop procedure if exists bug3448| -create procedure bug3448() -select * from t3 inner join t4 on t3.a = t4.b| -select * from t3 inner join t4 on t3.a = t4.b| -a ach b bch -1 a 1 b -call bug3448()| -a ach b bch -1 a 1 b -call bug3448()| -a ach b bch -1 a 1 b -drop procedure bug3448| -drop table t3, t4| -create table t3 ( id int unsigned auto_increment not null primary key, title VARCHAR(200), body text, @@ -4005,48 +3976,6 @@ DROP VIEW bug13095_v1 DROP PROCEDURE IF EXISTS bug13095; DROP VIEW IF EXISTS bug13095_v1; DROP TABLE IF EXISTS bug13095_t1; -drop procedure if exists bug14210| -set @@session.max_heap_table_size=16384| -select @@session.max_heap_table_size| -@@session.max_heap_table_size -16384 -create table t3 (a char(255)) engine=InnoDB| -create procedure bug14210_fill_table() -begin -declare table_size, max_table_size int default 0; -select @@session.max_heap_table_size into max_table_size; -delete from t3; -insert into t3 (a) values (repeat('a', 255)); -repeat -insert into t3 select a from t3; -select count(*)*255 from t3 into table_size; -until table_size > max_table_size*2 end repeat; -end| -call bug14210_fill_table()| -drop procedure bug14210_fill_table| -create table t4 like t3| -create procedure bug14210() -begin -declare a char(255); -declare done int default 0; -declare c cursor for select * from t3; -declare continue handler for sqlstate '02000' set done = 1; -open c; -repeat -fetch c into a; -if not done then -insert into t4 values (upper(a)); -end if; -until done end repeat; -close c; -end| -call bug14210()| -select count(*) from t4| -count(*) -256 -drop table t3, t4| -drop procedure bug14210| -set @@session.max_heap_table_size=default| drop function if exists bug14723| drop procedure if exists bug14723| /*!50003 create function bug14723() diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index e9289cf01c7..564e31c9e32 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -425,3 +425,108 @@ x y drop procedure bug14840_1| drop procedure bug14840_2| drop table t3| +drop procedure if exists bug10656_create_index| +drop procedure if exists bug10656_myjoin| +drop procedure if exists bug10656_truncate_table| +CREATE TABLE t3 ( +`ID` int(11) default NULL, +`txt` char(5) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1| +INSERT INTO t3 (`ID`,`txt`) VALUES +(1,'a'), (2,'b'), (3,'c'), (4,'d')| +CREATE TABLE t4 ( +`ID` int(11) default NULL, +`txt` char(5) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1| +INSERT INTO t4 (`ID`,`txt`) VALUES +(1,'a'), (2,'b'), (3,'c'), (4,'d')| +create procedure bug10656_create_index() +begin +create index bug10656_my_index on t3 (ID); +end| +call bug10656_create_index()| +create procedure bug10656_myjoin() +begin +update t3, t4 set t3.txt = t4.txt where t3.id = t4.id; +end| +call bug10656_myjoin()| +create procedure bug10656_truncate_table() +begin +truncate table t3; +end| +call bug10656_truncate_table()| +drop procedure bug10656_create_index| +drop procedure bug10656_myjoin| +drop procedure bug10656_truncate_table| +drop table t3, t4| +create table t3 ( +a int primary key, +ach char(1) +) engine = innodb| +create table t4 ( +b int primary key, +bch char(1) +) engine = innodb| +insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')| +Warnings: +Warning 1265 Data truncated for column 'ach' at row 1 +Warning 1265 Data truncated for column 'ach' at row 2 +insert into t4 values (1 , 'bCh1' )| +Warnings: +Warning 1265 Data truncated for column 'bch' at row 1 +drop procedure if exists bug3448| +create procedure bug3448() +select * from t3 inner join t4 on t3.a = t4.b| +select * from t3 inner join t4 on t3.a = t4.b| +a ach b bch +1 a 1 b +call bug3448()| +a ach b bch +1 a 1 b +call bug3448()| +a ach b bch +1 a 1 b +drop procedure bug3448| +drop table t3, t4| +drop procedure if exists bug14210| +set @@session.max_heap_table_size=16384| +select @@session.max_heap_table_size| +@@session.max_heap_table_size +16384 +create table t3 (a char(255)) engine=InnoDB| +create procedure bug14210_fill_table() +begin +declare table_size, max_table_size int default 0; +select @@session.max_heap_table_size into max_table_size; +delete from t3; +insert into t3 (a) values (repeat('a', 255)); +repeat +insert into t3 select a from t3; +select count(*)*255 from t3 into table_size; +until table_size > max_table_size*2 end repeat; +end| +call bug14210_fill_table()| +drop procedure bug14210_fill_table| +create table t4 like t3| +create procedure bug14210() +begin +declare a char(255); +declare done int default 0; +declare c cursor for select * from t3; +declare continue handler for sqlstate '02000' set done = 1; +open c; +repeat +fetch c into a; +if not done then +insert into t4 values (upper(a)); +end if; +until done end repeat; +close c; +end| +call bug14210()| +select count(*) from t4| +count(*) +256 +drop table t3, t4| +drop procedure bug14210| +set @@session.max_heap_table_size=default| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 243c1b413b7..e07821231e0 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -2602,38 +2602,6 @@ select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time| drop procedure bug3426| -# -# BUG#3448 -# ---disable_warnings -create table t3 ( - a int primary key, - ach char(1) -) engine = innodb| - -create table t4 ( - b int primary key , - bch char(1) -) engine = innodb| ---enable_warnings - -insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')| -insert into t4 values (1 , 'bCh1' )| - ---disable_warnings -drop procedure if exists bug3448| ---enable_warnings -create procedure bug3448() - select * from t3 inner join t4 on t3.a = t4.b| - -select * from t3 inner join t4 on t3.a = t4.b| -call bug3448()| -call bug3448()| - -drop procedure bug3448| -drop table t3, t4| - - # # BUG#3734 # @@ -4853,60 +4821,6 @@ DROP TABLE IF EXISTS bug13095_t1; delimiter |; -# -# BUG#14210: "Simple query with > operator on large table gives server -# crash" -# Check that cursors work in case when HEAP tables are converted to -# MyISAM -# ---disable_warnings -drop procedure if exists bug14210| ---enable_warnings -set @@session.max_heap_table_size=16384| -select @@session.max_heap_table_size| -# To trigger the memory corruption the original table must be InnoDB. -# No harm if it's not, so don't warn if the suite is run with --skip-innodb ---disable_warnings -create table t3 (a char(255)) engine=InnoDB| ---enable_warnings -create procedure bug14210_fill_table() -begin - declare table_size, max_table_size int default 0; - select @@session.max_heap_table_size into max_table_size; - delete from t3; - insert into t3 (a) values (repeat('a', 255)); - repeat - insert into t3 select a from t3; - select count(*)*255 from t3 into table_size; - until table_size > max_table_size*2 end repeat; -end| -call bug14210_fill_table()| -drop procedure bug14210_fill_table| -create table t4 like t3| - -create procedure bug14210() -begin - declare a char(255); - declare done int default 0; - declare c cursor for select * from t3; - declare continue handler for sqlstate '02000' set done = 1; - open c; - repeat - fetch c into a; - if not done then - insert into t4 values (upper(a)); - end if; - until done end repeat; - close c; -end| -call bug14210()| -select count(*) from t4| - -drop table t3, t4| -drop procedure bug14210| -set @@session.max_heap_table_size=default| - - # # BUG#1473: Dumping of stored functions seems to cause corruption in # the function body diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index b9bd4c938b3..1ea32316f1e 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -419,6 +419,140 @@ drop procedure bug14840_2| drop table t3| +# +# BUG#10656: Stored Procedure - Create index and Truncate table command error +# +--disable_warnings +drop procedure if exists bug10656_create_index| +drop procedure if exists bug10656_myjoin| +drop procedure if exists bug10656_truncate_table| +--enable_warnings + +CREATE TABLE t3 ( + `ID` int(11) default NULL, + `txt` char(5) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1| + +INSERT INTO t3 (`ID`,`txt`) VALUES + (1,'a'), (2,'b'), (3,'c'), (4,'d')| + +CREATE TABLE t4 ( + `ID` int(11) default NULL, + `txt` char(5) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1| + +INSERT INTO t4 (`ID`,`txt`) VALUES + (1,'a'), (2,'b'), (3,'c'), (4,'d')| + +create procedure bug10656_create_index() +begin + create index bug10656_my_index on t3 (ID); +end| +call bug10656_create_index()| + +create procedure bug10656_myjoin() +begin + update t3, t4 set t3.txt = t4.txt where t3.id = t4.id; +end| +call bug10656_myjoin()| + +create procedure bug10656_truncate_table() +begin + truncate table t3; +end| +call bug10656_truncate_table()| + + +drop procedure bug10656_create_index| +drop procedure bug10656_myjoin| +drop procedure bug10656_truncate_table| +drop table t3, t4| + +# +# BUG#3448 +# +--disable_warnings +create table t3 ( + a int primary key, + ach char(1) +) engine = innodb| + +create table t4 ( + b int primary key, + bch char(1) +) engine = innodb| +--enable_warnings + +insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')| +insert into t4 values (1 , 'bCh1' )| + +--disable_warnings +drop procedure if exists bug3448| +--enable_warnings +create procedure bug3448() + select * from t3 inner join t4 on t3.a = t4.b| + +select * from t3 inner join t4 on t3.a = t4.b| +call bug3448()| +call bug3448()| + +drop procedure bug3448| +drop table t3, t4| + +# +# BUG#14210: "Simple query with > operator on large table gives server +# crash" +# Check that cursors work in case when HEAP tables are converted to +# MyISAM +# +--disable_warnings +drop procedure if exists bug14210| +--enable_warnings +set @@session.max_heap_table_size=16384| +select @@session.max_heap_table_size| +# To trigger the memory corruption the original table must be InnoDB. +# No harm if it's not, so don't warn if the suite is run with --skip-innodb +--disable_warnings +create table t3 (a char(255)) engine=InnoDB| +--enable_warnings +create procedure bug14210_fill_table() +begin + declare table_size, max_table_size int default 0; + select @@session.max_heap_table_size into max_table_size; + delete from t3; + insert into t3 (a) values (repeat('a', 255)); + repeat + insert into t3 select a from t3; + select count(*)*255 from t3 into table_size; + until table_size > max_table_size*2 end repeat; +end| +call bug14210_fill_table()| +drop procedure bug14210_fill_table| +create table t4 like t3| + +create procedure bug14210() +begin + declare a char(255); + declare done int default 0; + declare c cursor for select * from t3; + declare continue handler for sqlstate '02000' set done = 1; + open c; + repeat + fetch c into a; + if not done then + insert into t4 values (upper(a)); + end if; + until done end repeat; + close c; +end| +call bug14210()| +select count(*) from t4| + +drop table t3, t4| +drop procedure bug14210| +set @@session.max_heap_table_size=default| + + # # BUG#NNNN: New bug synopsis # From 85d705b651cf9057f2d687294044f173880675c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Mar 2006 10:09:52 -0800 Subject: [PATCH 04/11] Porting fix that allows others to include compiled code with different parsers. Makes you wonder what I am up to, doesn't? configure.in: Adjusts bison to not create symbols that clash. sql/sql_analyse.cc: Adding define to make sure sql_yacc.h gets included. sql/sql_lex.cc: Fixing it so that sql_yacc.h is included sql/sql_lex.h: Fixing include rules sql/sql_parse.cc: Adding flag to compile sql_yacc.yy --- configure.in | 2 +- sql/sql_analyse.cc | 2 ++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 4 ++++ sql/sql_parse.cc | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 4e630de13d2..4ff90bb39bb 100644 --- a/configure.in +++ b/configure.in @@ -236,7 +236,7 @@ AC_PROG_INSTALL test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' # Not critical since the generated file is distributed -AC_PROG_YACC +AC_CHECK_PROGS(YACC, ['bison -y -p MYSQL']) AC_CHECK_PROG(PDFMANUAL, pdftex, manual.pdf) AC_CHECK_PROG(DVIS, tex, manual.dvi) diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 0e4198a5114..af9246c673a 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -27,6 +27,8 @@ #pragma implementation // gcc: Class implementation #endif +#define MYSQL_LEX 1 + #include "mysql_priv.h" #include "procedure.h" #include "sql_analyse.h" diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 49b0c70ff03..110c82f6926 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -17,6 +17,7 @@ /* A lexical scanner on a temporary buffer with a yacc interface */ +#define MYSQL_LEX 1 #include "mysql_priv.h" #include "item_create.h" #include diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8db059ae2fa..8bacc60d48d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -37,8 +37,12 @@ class sp_pcontext; #define LEX_YYSTYPE void * #else #include "lex_symbol.h" +#if MYSQL_LEX #include "sql_yacc.h" #define LEX_YYSTYPE YYSTYPE * +#else +#define LEX_YYSTYPE void * +#endif #endif /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 527a6a67811..ea559c70734 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -14,6 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define MYSQL_LEX 1 #include "mysql_priv.h" #include "sql_repl.h" #include "repl_failsafe.h" From 2fbd17779feb849bbbd7b30ac439196634a1d7e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Mar 2006 13:17:19 -0600 Subject: [PATCH 05/11] mysqltest.test: Fix typos. mysql-test/t/mysqltest.test: Fix typos. --- mysql-test/t/mysqltest.test | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index a93aa24e812..3968eb519e1 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -27,7 +27,7 @@ # ---------------------------------------------------------------------------- # $mysql_errno contains the return code of the last command -# send to the server. +# sent to the server. # ---------------------------------------------------------------------------- # get $mysql_errno before the first statement # $mysql_errno should be -1 @@ -50,7 +50,7 @@ select otto from (select 1 as otto) as t1; # ---------------------------------------------------------------------------- # Negative case(statement): -# The dervied table t1 does not contain a column named 'friedrich' . +# The derived table t1 does not contain a column named 'friedrich' . # --> ERROR 42S22: Unknown column 'friedrich' in 'field list and # --> 1054: Unknown column 'friedrich' in 'field list' # ---------------------------------------------------------------------------- @@ -68,7 +68,7 @@ select friedrich from (select 1 as otto) as t1; # The following unmasked unsuccessful statement must give # 1. mysqltest gives a 'failed' # 2. does not produce a r/.reject file !!! -# PLEASE uncomment it and check it's effect +# PLEASE uncomment it and check its effect #select friedrich from (select 1 as otto) as t1; @@ -114,7 +114,7 @@ select friedrich from (select 1 as otto) as t1; # test cases for $mysql_errno # # $mysql_errno is a builtin variable of mysqltest and contains the return code -# of the last command send to the server. +# of the last command sent to the server. # # The following test cases often initialize $mysql_errno to 1064 by # a command with wrong syntax. @@ -217,7 +217,7 @@ garbage ; execute stmt; eval select $mysql_errno as "after_successful_execute" ; -# failing execute (table dropped) +# failing execute (table has been dropped) drop table t1; --error 1064 garbage ; @@ -249,8 +249,8 @@ eval select $mysql_errno as "after_failing_deallocate" ; # ---------------------------------------------------------------------------- # test cases for "--disable_abort_on_error" # -# "--disable_abort_on_error" switches the abort of mysqltest -# after "unmasked" failing statements off. +# "--disable_abort_on_error" switches off the abort of mysqltest +# after "unmasked" failing statements. # # The default is "--enable_abort_on_error". # @@ -258,13 +258,13 @@ eval select $mysql_errno as "after_failing_deallocate" ; # --error and --error # in the line before the failing statement. # -# There are some additional test case for $mysql_errno +# There are some additional test cases for $mysql_errno # because "--disable_abort_on_error" enables a new situation. # Example: "unmasked" statement fails + analysis of $mysql_errno # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Switch the abort on error off and check the effect on $mysql_errno +# Switch off the abort on error and check the effect on $mysql_errno # ---------------------------------------------------------------------------- --error 1064 garbage ; @@ -345,7 +345,7 @@ select 3 from t1 ; # ---------------------------------------------------------------------------- # Test detect end of line "junk" -# Most likely causes by a missing delimiter +# Most likely caused by a missing delimiter # ---------------------------------------------------------------------------- # Too many parameters to function @@ -1043,7 +1043,7 @@ let $message= . Here comes a very very long message that --source include/show_msg80.inc # -# Test --enable_parsning / disable_parsning +# Test --enable_parsing / disable_parsing # --disable_query_log --disable_parsing @@ -1070,9 +1070,9 @@ select "this will be executed"; # # Test that mysqltest fails when there are no queries executed -# but a result file exist +# but a result file exists # NOTE! This will never happen as long as it's not allowed to have -# test files that does not produce any output +# test files that produce no output #--exec echo "something" > $MYSQLTEST_VARDIR/tmp/result_file.result #--exec echo "let \$i= 1;" > $MYSQLTEST_VARDIR/tmp/query.sql #--error 1 From 01d69c4b966015a7fc5806d337e3006b22baed47 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Mar 2006 16:44:08 -0800 Subject: [PATCH 06/11] This patch does 1) fix my build breakage 2) Complete the removal of all symbols which could clash with another parser. sql/mysql_priv.h: Porting update sql/mysqld.cc: Porting update sql/sp.cc: Porting update sql/sql_lex.cc: Porting update sql/sql_lex.h: Porting update sql/sql_parse.cc: Porting update sql/sql_prepare.cc: Portinng update sql/sql_trigger.cc: Porting update sql/sql_view.cc: Porting update --- sql/mysql_priv.h | 4 ++-- sql/mysqld.cc | 2 +- sql/sp.cc | 4 ++-- sql/sql_lex.cc | 4 ++-- sql/sql_lex.h | 4 ++-- sql/sql_parse.cc | 6 +++--- sql/sql_prepare.cc | 2 +- sql/sql_trigger.cc | 3 ++- sql/sql_view.cc | 3 ++- 9 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a43307edf27..68679cf79dc 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1093,7 +1093,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg); /* mysqld.cc */ -extern void yyerror(const char*); +extern void MYSQLerror(const char*); /* item_func.cc */ extern bool check_reserved_words(LEX_STRING *name); @@ -1415,7 +1415,7 @@ void free_list(I_List *list); void free_list(I_List *list); /* sql_yacc.cc */ -extern int yyparse(void *thd); +extern int MYSQLparse(void *thd); /* frm_crypt.cc */ #ifdef HAVE_CRYPTED_FRM diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 37a135fa063..bc30a2c981b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1524,7 +1524,7 @@ static void network_init(void) #endif /*!EMBEDDED_LIBRARY*/ -void yyerror(const char *s) +void MYSQLerror(const char *s) { THD *thd=current_thd; char *yytext= (char*) thd->lex->tok_start; diff --git a/sql/sp.cc b/sql/sp.cc index e4489af1fdd..0446bf94e53 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -269,7 +269,7 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table) static int db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) { - extern int yyparse(void *thd); + extern int MYSQLparse(void *thd); TABLE *table; const char *params, *returns, *body; int ret; @@ -459,7 +459,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length()); thd->spcont= 0; - if (yyparse(thd) || thd->is_fatal_error || newlex.sphead == NULL) + if (MYSQLparse(thd) || thd->is_fatal_error || newlex.sphead == NULL) { sp_head *sp= newlex.sphead; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 110c82f6926..2b31abd6a50 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -507,14 +507,14 @@ static inline uint int_token(const char *str,uint length) } /* - yylex remember the following states from the following yylex() + MYSQLlex remember the following states from the following MYSQLlex() - MY_LEX_EOQ Found end of query - MY_LEX_OPERATOR_OR_IDENT Last state was an ident, text or number (which can't be followed by a signed number) */ -int yylex(void *arg, void *yythd) +int MYSQLlex(void *arg, void *yythd) { reg1 uchar c; int tokval, result_state; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8bacc60d48d..8512c075f69 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -716,7 +716,7 @@ typedef struct st_lex uchar *buf; /* The beginning of string, used by SPs */ uchar *ptr,*tok_start,*tok_end,*end_of_query; - /* The values of tok_start/tok_end as they were one call of yylex before */ + /* The values of tok_start/tok_end as they were one call of MYSQLlex before */ uchar *tok_start_prev, *tok_end_prev; char *length,*dec,*change,*name; @@ -1065,7 +1065,7 @@ extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd, uchar *buf,uint length); extern void lex_end(LEX *lex); -extern int yylex(void *arg, void *yythd); +extern int MYSQLlex(void *arg, void *yythd); extern pthread_key(LEX*,THR_LEX); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ea559c70734..489afe79b5e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4244,7 +4244,7 @@ end_with_restore_list: /* We must cleanup the unit and the lex here because sp_grant_privileges calls (indirectly) db_find_routine, - which in turn may call yyparse with THD::lex. + which in turn may call MYSQLparse with THD::lex. TODO: fix db_find_routine to use a temporary lex. */ lex->unit.cleanup(); @@ -5659,7 +5659,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length) sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); - if (!yyparse((void *)thd) && ! thd->is_fatal_error) + if (!MYSQLparse((void *)thd) && ! thd->is_fatal_error) { #ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && @@ -5739,7 +5739,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) DBUG_ENTER("mysql_test_parse_for_slave"); mysql_init_query(thd, (uchar*) inBuf, length); - if (!yyparse((void*) thd) && ! thd->is_fatal_error && + if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) error= 1; /* Ignore question */ thd->end_statement(); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 332f699200e..0f4ae04962b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2757,7 +2757,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) lex->safe_to_cache_query= FALSE; lex->stmt_prepare_mode= TRUE; - error= yyparse((void *)thd) || thd->is_fatal_error || + error= MYSQLparse((void *)thd) || thd->is_fatal_error || thd->net.report_error || init_param_array(this); /* While doing context analysis of the query (in check_prepared_statement) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 024c882f8a9..b432961b7e6 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define MYSQL_LEX 1 #include "mysql_priv.h" #include "sp_head.h" #include "sql_trigger.h" @@ -932,7 +933,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length); thd->spcont= 0; - if (yyparse((void *)thd) || thd->is_fatal_error) + if (MYSQLparse((void *)thd) || thd->is_fatal_error) { /* Free lex associated resources. diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4f2a9a07705..2832adc1f8f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define MYSQL_LEX 1 #include "mysql_priv.h" #include "sql_select.h" #include "parse_file.h" @@ -889,7 +890,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table) MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES); CHARSET_INFO *save_cs= thd->variables.character_set_client; thd->variables.character_set_client= system_charset_info; - res= yyparse((void *)thd); + res= MYSQLparse((void *)thd); thd->variables.character_set_client= save_cs; thd->variables.sql_mode= save_mode; } From 50c8c206fca3ea3b7ca6978ba1fe283f9777db4d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 13:53:00 +0300 Subject: [PATCH 07/11] Fixed bug#13575: SP funcs in select with distinct/group and order by can produce wrong data By default Item_sp_func::val_str() returns string from it's result_field internal buffer. When grouping is present Item_copy_string is used to store SP function result, but it doesn't additionally buffer the result. When the next record is read, internal buffer is overwritten, due to this Item_copy_string::val_str() will have wrong data. Thus producing weird query result. The Item_func_sp::val_str() now makes a copy of returned value to prevent occasional corruption. mysql-test/t/sp.test: Added test case for bug#13575: SP funcs in select with distinct/group and order by can produce wrong data mysql-test/r/sp.result: Added test case for bug#13575: SP funcs in select with distinct/group and order by can produce wrong data sql/item_func.h: Fixed bug#13575: SP funcs in select with distinct/group and order by can produce wrong data The Item_func_sp::val_str() now makes a copy of returned value to prevent occasinal corruption. --- mysql-test/r/sp.result | 16 ++++++++++++++++ mysql-test/t/sp.test | 16 ++++++++++++++++ sql/item_func.h | 14 +++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 45e8e0ce55a..fd09e9c8e94 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4786,4 +4786,20 @@ i 0 drop table t3| drop procedure bug16887| +create table t3 (f1 int, f2 varchar(3), primary key(f1)) engine=innodb| +insert into t3 values (1,'aaa'),(2,'bbb'),(3,'ccc')| +CREATE FUNCTION bug13575 ( p1 integer ) +returns varchar(3) +BEGIN +DECLARE v1 VARCHAR(10) DEFAULT null; +SELECT f2 INTO v1 FROM t3 WHERE f1 = p1; +RETURN v1; +END| +select distinct f1, bug13575(f1) from t3 order by f1| +f1 bug13575(f1) +1 aaa +2 bbb +3 ccc +drop function bug13575; +drop table t3| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index c00caf10adb..ee7b05498fd 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5630,6 +5630,22 @@ call bug16887()| drop table t3| drop procedure bug16887| +# +# Bug#13575 SP funcs in select with distinct/group and order by can +# produce bad data +# +create table t3 (f1 int, f2 varchar(3), primary key(f1)) engine=innodb| +insert into t3 values (1,'aaa'),(2,'bbb'),(3,'ccc')| +CREATE FUNCTION bug13575 ( p1 integer ) +returns varchar(3) +BEGIN +DECLARE v1 VARCHAR(10) DEFAULT null; +SELECT f2 INTO v1 FROM t3 WHERE f1 = p1; +RETURN v1; +END| +select distinct f1, bug13575(f1) from t3 order by f1| +drop function bug13575; +drop table t3| # # BUG#NNNN: New bug synopsis diff --git a/sql/item_func.h b/sql/item_func.h index d8fa45fb9c0..ccbbbab1df4 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1421,9 +1421,21 @@ public: String *val_str(String *str) { + String buf; + char buff[20]; + buf.set(buff, 20, str->charset()); + buf.length(0); if (execute(&result_field)) return NULL; - return result_field->val_str(str); + /* + result_field will set buf pointing to internal buffer + of the resul_field. Due to this it will change any time + when SP is executed. In order to prevent occasional + corruption of returned value, we make here a copy. + */ + result_field->val_str(&buf); + str->copy(buf); + return str; } virtual bool change_context_processor(byte *cntx) From cf539a5ac0420bb15d9eed06998510be4bb46598 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 14:40:15 +0300 Subject: [PATCH 08/11] Additional fix for BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables specified. The previous patch does not allow to specify empty host name in DEFINER-clause explicitly. mysql-test/r/skip_grants.result: Updated the result file. mysql-test/r/view_grant.result: Updated the result file. mysql-test/t/skip_grants.test: Added test cases for BUG#16777; re-organized tests. mysql-test/t/view_grant.test: Updated after final fix of BUG#16777. sql/sql_parse.cc: The final part of fixing BUG#16777: allow empty host name in explicitly specified DEFINER-clause. sql/sql_show.cc: Quote an identifier if it is empty. --- mysql-test/r/skip_grants.result | 54 +++++++++++++++----- mysql-test/r/view_grant.result | 11 +++-- mysql-test/t/skip_grants.test | 88 +++++++++++++++++++++++---------- mysql-test/t/view_grant.test | 7 ++- sql/sql_parse.cc | 11 +---- sql/sql_show.cc | 21 ++++++-- 6 files changed, 135 insertions(+), 57 deletions(-) diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index 6714fa9d217..58ced16acac 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -1,30 +1,60 @@ -drop table if exists t1,v1; -drop view if exists t1,v1; -drop procedure if exists f1; use test; -create procedure f1() select 1; -drop procedure f1; -create table t1 (a int); -create definer='user'@'host' sql security definer view v1 as select * from t1; -drop view v1; -drop table t1; -drop function if exists f1; -Warnings: -Note 1305 FUNCTION f1 does not exist DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; CREATE TABLE t1(c INT); CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; CREATE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1() +SELECT 1; +CREATE FUNCTION f1() RETURNS INT +RETURN 1; CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 FOR EACH ROW SET @b = 1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; +CREATE DEFINER=a@b PROCEDURE p2() +SELECT 2; +CREATE DEFINER=a@b FUNCTION f2() RETURNS INT +RETURN 2; +CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1 +FOR EACH ROW +SET @c = 1; +CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1; +CREATE DEFINER=a@'' PROCEDURE p3() +SELECT 3; +CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT +RETURN 3; +SHOW CREATE VIEW v3; +View Create View +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`a`@`` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`c` AS `c` from `t1` +SHOW CREATE PROCEDURE p3; +Procedure sql_mode Create Procedure +p3 CREATE DEFINER=`a`@`` PROCEDURE `p3`() +SELECT 3 +SHOW CREATE FUNCTION f3; +Function sql_mode Create Function +f3 CREATE DEFINER=`a`@`` FUNCTION `f3`() RETURNS int(11) +RETURN 3 DROP TRIGGER t1_bi; DROP TRIGGER ti_ai; +DROP TRIGGER ti_bu; DROP VIEW v1; DROP VIEW v2; +DROP VIEW v3; DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 46fb4698838..3feffb4a510 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -520,11 +520,16 @@ use test; drop user mysqltest_1@localhost; drop database mysqltest; create definer=some_user@`` sql security invoker view v1 as select 1; -ERROR HY000: Definer is not fully qualified -create definer=some_user@localhost sql security invoker view v1 as select 1; +Warnings: +Note 1449 There is no 'some_user'@'' registered +create definer=some_user@localhost sql security invoker view v2 as select 1; Warnings: Note 1449 There is no 'some_user'@'localhost' registered show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` +show create view v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1` drop view v1; +drop view v2; diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 93e052d8c71..6dda97fcf8a 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -1,37 +1,18 @@ # This tests not performed with embedded server -- source include/not_embedded.inc ---disable_warnings -drop table if exists t1,v1; -drop view if exists t1,v1; -drop procedure if exists f1; ---enable_warnings use test; -# -# Test that we can create and drop procedure without warnings -# see bug#9993 -# -create procedure f1() select 1; -drop procedure f1; - -# -# BUG#13504: creation view with DEFINER clause if --skip-grant-tables -# -create table t1 (a int); -create definer='user'@'host' sql security definer view v1 as select * from t1; -drop view v1; -drop table t1; - -# BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server -drop function if exists f1; - # # BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables # specified # -# Also, a test that we can create VIEW if privileges check switched off has -# been moved here. +# Also, the following test cases have been moved here: +# - test that we can create VIEW if privileges check switched off has been +# moved here; +# - test that we can create and drop procedure without warnings (BUG#9993); +# - BUG#17595: "DROP FUNCTION IF EXISTS" crashes server; +# - BUG#13504: creation view with DEFINER clause if --skip-grant-tables # # Prepare. @@ -40,33 +21,90 @@ drop function if exists f1; DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; + +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; + --enable_warnings # Test case. CREATE TABLE t1(c INT); +# - try to create with implicit definer (definer would be ''@''); + CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; CREATE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1() + SELECT 1; + +CREATE FUNCTION f1() RETURNS INT + RETURN 1; + +# - try to create with explicit definer; + CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1 FOR EACH ROW SET @b = 1; CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1; +CREATE DEFINER=a@b PROCEDURE p2() + SELECT 2; + +CREATE DEFINER=a@b FUNCTION f2() RETURNS INT + RETURN 2; + +# - try to create with explicit definer with empty host; + +CREATE DEFINER=a@'' TRIGGER ti_bu BEFORE UPDATE ON t1 + FOR EACH ROW + SET @c = 1; + +CREATE DEFINER=a@'' VIEW v3 AS SELECT * FROM t1; + +CREATE DEFINER=a@'' PROCEDURE p3() + SELECT 3; + +CREATE DEFINER=a@'' FUNCTION f3() RETURNS INT + RETURN 3; + +# - check that empty host name is treated correctly; + +SHOW CREATE VIEW v3; + +SHOW CREATE PROCEDURE p3; + +SHOW CREATE FUNCTION f3; + # Cleanup. DROP TRIGGER t1_bi; DROP TRIGGER ti_ai; +DROP TRIGGER ti_bu; DROP VIEW v1; DROP VIEW v2; +DROP VIEW v3; DROP TABLE t1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 87478a9d4b2..e80e1770ba2 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -706,10 +706,9 @@ connection default; # # DEFINER information check # --- error ER_MALFORMED_DEFINER create definer=some_user@`` sql security invoker view v1 as select 1; -create definer=some_user@localhost sql security invoker view v1 as select 1; +create definer=some_user@localhost sql security invoker view v2 as select 1; show create view v1; +show create view v2; drop view v1; - - +drop view v2; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 489afe79b5e..d9f5499f362 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7300,8 +7300,7 @@ LEX_USER *create_default_definer(THD *thd) /* - Create definer with the given user and host names. Also check that the user - and host names satisfy definers requirements. + Create definer with the given user and host names. SYNOPSIS create_definer() @@ -7319,14 +7318,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) { LEX_USER *definer; - /* Check that specified host name is valid. */ - - if (host_name->length == 0) - { - my_error(ER_MALFORMED_DEFINER, MYF(0)); - return 0; - } - /* Create and initialize. */ if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5c9d13cac3e..403781b330d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -648,6 +648,18 @@ static const char *require_quotes(const char *name, uint name_length) } +/* + Quote the given identifier if needed and append it to the target string. + If the given identifier is empty, it will be quoted. + + SYNOPSIS + append_identifier() + thd thread handler + packet target string + name the identifier to be appended + name_length length of the appending identifier +*/ + void append_identifier(THD *thd, String *packet, const char *name, uint length) { @@ -701,8 +713,11 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) length length of name IMPLEMENTATION - If name is a keyword or includes a special character, then force - quoting. + Force quoting in the following cases: + - name is empty (for one, it is possible when we use this function for + quoting user and host names for DEFINER clause); + - name is a keyword; + - name includes a special character; Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE is set. @@ -713,7 +728,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) int get_quote_char_for_identifier(THD *thd, const char *name, uint length) { - if (!length || + if (length && !is_keyword(name,length) && !require_quotes(name, length) && !(thd->options & OPTION_QUOTE_SHOW_CREATE)) From fbe17c2a36dcaa99c5a6570f7096745126113301 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 15:03:04 +0100 Subject: [PATCH 09/11] Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX For "count(*) while index_column = value" an index read is done. It consists of an index scan and retrieval of each key. For efficiency reasons the index scan stores the key in the special buffer 'lastkey2' once only. At the first iteration it notes this fact with the flag HA_STATE_RNEXT_SAME in 'info->update'. For efficiency reasons, the key retrieval for blobs does not allocate a new buffer, but uses 'lastkey2'... Now I clear the HA_STATE_RNEXT_SAME flag whenever the buffer has been polluted. In this case, the index scan copies the key value again (and sets the flag again). include/my_base.h: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Changed the comment for HA_STATE_RNEXT_SAME as a warning for future uses. myisam/mi_delete.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removing the flag HA_STATE_RNEXT_SAME from info->update if info->lastkey2 was reused for another purpose than index scanning. myisam/mi_key.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removing the flag HA_STATE_RNEXT_SAME from info->update if info->lastkey2 was reused for another purpose than index scanning. myisam/mi_rnext_same.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removed trailing space and fixed a comment. myisam/mi_unique.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removing the flag HA_STATE_RNEXT_SAME from info->update if info->lastkey2 was reused for another purpose than index scanning. myisam/mi_update.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removing the flag HA_STATE_RNEXT_SAME from info->update if info->lastkey2 was reused for another purpose than index scanning. myisam/mi_write.c: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Removing the flag HA_STATE_RNEXT_SAME from info->update if info->lastkey2 was reused for another purpose than index scanning. mysql-test/r/myisam.result: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Added test result. mysql-test/t/myisam.test: Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX Added test. --- include/my_base.h | 2 +- myisam/mi_delete.c | 2 ++ myisam/mi_key.c | 4 ++++ myisam/mi_rnext_same.c | 4 ++-- myisam/mi_unique.c | 3 +++ myisam/mi_update.c | 4 ++++ myisam/mi_write.c | 4 ++++ mysql-test/r/myisam.result | 18 ++++++++++++++++++ mysql-test/t/myisam.test | 19 +++++++++++++++++++ 9 files changed, 57 insertions(+), 3 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 271e7cd23ba..1261a95175f 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -340,7 +340,7 @@ enum ha_base_keytype { #define HA_STATE_BUFF_SAVED 512 /* If current keybuff is info->buff */ #define HA_STATE_ROW_CHANGED 1024 /* To invalide ROW cache */ #define HA_STATE_EXTEND_BLOCK 2048 -#define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */ +#define HA_STATE_RNEXT_SAME 4096 /* rnext_same occupied lastkey2 */ enum en_fieldtype { FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 6c302aecea1..00699e8b089 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -82,6 +82,8 @@ int mi_delete(MI_INFO *info,const byte *record) _mi_make_key(info,i,old_key,record,info->lastpos))) goto err; } + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; } } diff --git a/myisam/mi_key.c b/myisam/mi_key.c index f4b92f969db..cb85febd869 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -393,6 +393,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, (char*) &blob_ptr,sizeof(char*)); memcpy(blob_ptr,key,length); blob_ptr+=length; + + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; + _my_store_blob_length(record+keyseg->start, (uint) keyseg->bit_start,length); key+=length; diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c index 92692d0517f..64d8d9b0baa 100644 --- a/myisam/mi_rnext_same.c +++ b/myisam/mi_rnext_same.c @@ -40,7 +40,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf) if (info->s->concurrent_insert) rw_rdlock(&info->s->key_root_lock[inx]); - + switch (keyinfo->key_alg) { #ifdef HAVE_RTREE_KEYS @@ -102,4 +102,4 @@ int mi_rnext_same(MI_INFO *info, byte *buf) DBUG_RETURN(0); } DBUG_RETURN(my_errno); -} /* mi_rnext */ +} /* mi_rnext_same */ diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index ad685f4cbdc..b5baa448609 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -30,6 +30,9 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record, mi_unique_store(record+key->seg->start, unique_hash); _mi_make_key(info,def->key,key_buff,record,0); + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; + if (_mi_search(info,info->s->keyinfo+def->key,key_buff,MI_UNIQUE_HASH_LENGTH, SEARCH_FIND,info->s->state.key_root[def->key])) { diff --git a/myisam/mi_update.c b/myisam/mi_update.c index f62be133ed9..672c8407353 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -108,6 +108,10 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) { uint new_length=_mi_make_key(info,i,new_key,newrec,pos); uint old_length=_mi_make_key(info,i,old_key,oldrec,pos); + + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; + if (new_length != old_length || memcmp((byte*) old_key,(byte*) new_key,new_length)) { diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 52455320515..720c96b2d38 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -128,6 +128,10 @@ int mi_write(MI_INFO *info, byte *record) goto err; } } + + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; + if (local_lock_tree) rw_unlock(&share->key_root_lock[i]); } diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index c269cbadca3..3b4519e5444 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -730,3 +730,21 @@ select * from t1 where bob is null and cip=1; cip time score bob 1 00:01:00 0 NULL drop table t1; +create table t1 ( +id1 int not null auto_increment, +id2 int not null default '0', +t text not null, +primary key (id1), +key x (id2, t(32)) +) engine=myisam; +insert into t1 (id2, t) values +(10, 'abc'), (10, 'abc'), (10, 'abc'), +(20, 'abc'), (20, 'abc'), (20, 'def'), +(10, 'abc'), (10, 'abc'); +select count(*) from t1 where id2 = 10; +count(*) +5 +select count(id1) from t1 where id2 = 10; +count(id1) +5 +drop table t1; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index ce40cae3266..7e4cc324b12 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -686,4 +686,23 @@ select * from t1 where bob is null and cip=1; create index bug on t1 (bob(22), cip, time); select * from t1 where bob is null and cip=1; drop table t1; + +# +# Bug#14980 - COUNT(*) incorrect on MyISAM table with certain INDEX +# +create table t1 ( + id1 int not null auto_increment, + id2 int not null default '0', + t text not null, + primary key (id1), + key x (id2, t(32)) +) engine=myisam; +insert into t1 (id2, t) values +(10, 'abc'), (10, 'abc'), (10, 'abc'), +(20, 'abc'), (20, 'abc'), (20, 'def'), +(10, 'abc'), (10, 'abc'); +select count(*) from t1 where id2 = 10; +select count(id1) from t1 where id2 = 10; +drop table t1; + # End of 4.1 tests From 7ec0c0d9bc2813269c3fe50bef5b36fcdbb3b39e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 17:13:54 +0100 Subject: [PATCH 10/11] Include the system header file "pthread.h" even in a non-threaded build. Fixes bug#15861 include/my_no_pthread.h: Even in a non-threaded build, some modules (at least "mysys/mf_keycache.c") need some type definitions provided by the system header file "pthread.h". Rather than add complexity to the code, include the header. Fixes bug#15861 --- include/my_no_pthread.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index 2c9cde65e78..5691de08783 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -14,15 +14,34 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#if !defined(_my_no_pthread_h) && !defined(THREAD) +#define _my_no_pthread_h + + +/* + This block is to access some thread-related type definitions + even in builds which do not need thread functions, + as some variables (based on these types) are declared + even in non-threaded builds. + Case in point: 'mf_keycache.c' +*/ +#if defined(__WIN__) || defined(OS2) + +#elif defined(HAVE_UNIXWARE7_THREADS) +/* #include Currently, not relevant. Enable if needed. */ + +#else /* Normal threads */ +#include + +#endif /* defined(__WIN__) */ + + /* This undefs some pthread mutex locks when one isn't using threads to make thread safe code, that should also work in single thread environment, easier to use. */ - -#if !defined(_my_no_pthread_h) && !defined(THREAD) -#define _my_no_pthread_h - #define pthread_mutex_init(A,B) #define pthread_mutex_lock(A) #define pthread_mutex_unlock(A) @@ -32,4 +51,5 @@ #define rw_wrlock(A) #define rw_unlock(A) #define rwlock_destroy(A) + #endif From dafa39f1c42a55af06b89e091c2b214128d8c82f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 22:23:04 +0300 Subject: [PATCH 11/11] Fix version of DEFINER-clause in mysqldump. Now DEFINER-clause in stored routines is expected to appear in 5.0.20 release, not in 5.0.19. as it was supposed before. client/mysqldump.c: Fixing version. mysql-test/r/mysqldump.result: Updated the result file. --- client/mysqldump.c | 2 +- mysql-test/r/mysqldump.result | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index e0469e00031..78f12593f46 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1342,7 +1342,7 @@ static uint dump_routines_for_db(char *db) query_str_tail= strnmov(query_str, row[2], definer_begin - row[2]); - query_str_tail= strmov(query_str_tail, "*/ /*!50019"); + query_str_tail= strmov(query_str_tail, "*/ /*!50020"); query_str_tail= strnmov(query_str_tail, definer_begin, definer_end - definer_begin); query_str_tail= strxmov(query_str_tail, "*/ /*!50003", diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index e6ac9fbc740..94bc56b6cb7 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2210,12 +2210,12 @@ UNLOCK TABLES; DELIMITER ;; /*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */;; /*!50003 SET SESSION SQL_MODE=""*/;; -/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) +/*!50003 CREATE*/ /*!50020 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) RETURN a+b */;; /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; /*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */;; /*!50003 SET SESSION SQL_MODE=""*/;; -/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1) +/*!50003 CREATE*/ /*!50020 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1) begin set f1= concat( 'hello', f1 ); return f1; @@ -2223,17 +2223,17 @@ end */;; /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; /*!50003 DROP PROCEDURE IF EXISTS `a'b` */;; /*!50003 SET SESSION SQL_MODE="REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI"*/;; -/*!50003 CREATE*/ /*!50019 DEFINER="root"@"localhost"*/ /*!50003 PROCEDURE "a'b"() +/*!50003 CREATE*/ /*!50020 DEFINER="root"@"localhost"*/ /*!50003 PROCEDURE "a'b"() select 1 */;; /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */;; /*!50003 SET SESSION SQL_MODE=""*/;; -/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT) +/*!50003 CREATE*/ /*!50020 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT) BEGIN SELECT a+b INTO c; end */;; /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */;; /*!50003 SET SESSION SQL_MODE=""*/;; -/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT) +/*!50003 CREATE*/ /*!50020 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT) BEGIN select sum(id) from t1 into a; END */;;