diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 69d8b6e0f67..ddb52ce9014 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -28,7 +28,7 @@ ADD_LIBRARY(mysqldemb emb_qcache.cc libmysqld.c lib_sql.cc ../client/get_password.c ../libmysql/errmsg.c ../libmysql/libmysql.c ../sql/password.c ../sql-common/client.c ../sql-common/my_time.c ../sql-common/my_user.c - ../sql-common/pack.c ../sql/derror.cc ../sql/event_executor.cc + ../sql-common/pack.c ../sql/derror.cc ../sql/event_scheduler.cc ../sql/event_timed.cc ../sql/events.cc ../sql/discover.cc ../sql/field_conv.cc ../sql/field.cc ../sql/filesort.cc ../sql/gstream.cc ../sql/ha_heap.cc ../sql/ha_myisam.cc diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 5b5bdc8fc35..7f7a0cc436c 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -361,12 +361,6 @@ extract(SECOND FROM "1999-01-02 10:11:12") select extract(MONTH FROM "2001-02-00"); extract(MONTH FROM "2001-02-00") 2 -SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) -9999-12-31 00:00:00 -SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) -9999-12-31 00:00:00 SELECT EXTRACT(QUARTER FROM '2004-01-15') AS quarter; quarter 1 @@ -403,6 +397,12 @@ quarter SELECT EXTRACT(QUARTER FROM '2004-12-15') AS quarter; quarter 4 +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND 1968-01-20 03:14:08 diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 363c5296a1b..a472aa0c68d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -310,26 +310,26 @@ show create function sub1; ERROR 42000: FUNCTION sub1 does not exist select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL grant all privileges on test.* to mysqltest_1@localhost; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL create function sub2(i int) returns int return i+1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL sub2 return i+1 show create procedure sel2; Procedure sql_mode Create Procedure -sel2 +sel2 NULL show create function sub1; Function sql_mode Create Function -sub1 +sub1 NULL show create function sub2; Function sql_mode Create Function sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11) @@ -1182,6 +1182,43 @@ concat(@a, table_name) @a table_name .t1 . t1 .t2 . t2 drop table t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 RETURN @a + 1 +p1 SET @a= 1 +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +SET @a= 1 +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) +RETURN @a + 1 +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 NULL +p1 NULL +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 NULL +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 NULL +CALL p1(); +SELECT f1(); +f1() +2 +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; +End of 5.0 tests. select * from information_schema.engines WHERE ENGINE="MyISAM"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO @@ -1190,3 +1227,4 @@ select user,db from information_schema.processlist; user db user3148 test drop user user3148@localhost; +End of 5.1 tests. diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index e18bc51f981..e95489864f7 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1078,4 +1078,43 @@ a 2 1 drop table t1; +create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart00, SUBPARTITION subpart01)); +hello/master-data/test/t1#P#p0#SP#subpart00.MYD +hello/master-data/test/t1#P#p0#SP#subpart00.MYI +hello/master-data/test/t1#P#p0#SP#subpart01.MYD +hello/master-data/test/t1#P#p0#SP#subpart01.MYI +hello/master-data/test/t1.frm +hello/master-data/test/t1.par +hello/master-data/tmpdata/t1#P#p0#SP#subpart00.MYD +hello/master-data/tmpdata/t1#P#p0#SP#subpart01.MYD +hello/master-data/tmpinx/t1#P#p0#SP#subpart00.MYI +hello/master-data/tmpinx/t1#P#p0#SP#subpart01.MYI +ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart10, SUBPARTITION subpart11), +partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart20, SUBPARTITION subpart21)); +hello/master-data/test/t1#P#p1#SP#subpart10.MYD +hello/master-data/test/t1#P#p1#SP#subpart10.MYI +hello/master-data/test/t1#P#p1#SP#subpart11.MYD +hello/master-data/test/t1#P#p1#SP#subpart11.MYI +hello/master-data/test/t1#P#p2#SP#subpart20.MYD +hello/master-data/test/t1#P#p2#SP#subpart20.MYI +hello/master-data/test/t1#P#p2#SP#subpart21.MYD +hello/master-data/test/t1#P#p2#SP#subpart21.MYI +hello/master-data/test/t1.frm +hello/master-data/test/t1.par +hello/master-data/tmpdata/t1#P#p1#SP#subpart10.MYD +hello/master-data/tmpdata/t1#P#p1#SP#subpart11.MYD +hello/master-data/tmpdata/t1#P#p2#SP#subpart20.MYD +hello/master-data/tmpdata/t1#P#p2#SP#subpart21.MYD +hello/master-data/tmpinx/t1#P#p1#SP#subpart10.MYI +hello/master-data/tmpinx/t1#P#p1#SP#subpart11.MYI +hello/master-data/tmpinx/t1#P#p2#SP#subpart20.MYI +hello/master-data/tmpinx/t1#P#p2#SP#subpart21.MYI +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index 0f2c8c57872..f64ffaff495 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -24,3 +24,15 @@ hello/master-data/test/t1#P#p0.MYD hello/master-data/test/t1#P#p0.MYI hello/master-data/test/t1.frm hello/master-data/test/t1.par +drop table t1; +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), +partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), +partition p12 values in (3,4)); +drop table t1; diff --git a/mysql-test/r/partition_order.result b/mysql-test/r/partition_order.result index 7a1ab1d6dc8..78ff7cd3121 100644 --- a/mysql-test/r/partition_order.result +++ b/mysql-test/r/partition_order.result @@ -718,7 +718,11 @@ partitions 2 partition x2 values less than (100)); INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); @@ -727,7 +731,55 @@ a b 5 NULL 40 NULL 1 1 +7 1 35 2 +3 3 +2 4 30 4 -2 5 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b; +a b +1 1 +7 1 +35 2 +3 3 +2 4 +30 4 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +a b +6 6 +4 5 +2 4 +30 4 +3 3 +35 2 +7 1 +1 1 +drop table t1; +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), +partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL +select * from t1 where a = 1 order by b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL drop table t1; diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 3cbb517053a..9123c894f32 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -519,3 +519,115 @@ partition p3 values less than (1998), partition p4 values less than (1999), partition p5 values less than (2000)); drop table t1; +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), +PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), +PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), +PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), +PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), +PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), +PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), +PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), +PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), +PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), +PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), +PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), +PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), +PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), +PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), +PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), +PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), +PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), +PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), +PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), +PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), +PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), +PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), +PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), +PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), +PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), +PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), +PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), +PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), +PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), +PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), +PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR +(a >= '2005-07-01' AND a <= '2005-09-30'); +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +2005-07-13 +2005-07-20 +2005-07-30 +2005-08-13 +2005-08-20 +2005-08-30 +2005-09-13 +2005-09-20 +2005-09-30 +EXPLAIN PARTITIONS SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR +(a >= '2005-07-01' AND a <= '2005-09-30'); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where +DROP TABLE t1; diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index f620cd657f0..6335870caa9 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -1075,3 +1075,18 @@ SELECT f1(); f1() abc DROP FUNCTION f1; +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE v_char VARCHAR(255); +DECLARE v_text TEXT DEFAULT ''; +SET v_char = 'abc'; +SET v_text = v_char; +SET v_char = 'def'; +SET v_text = concat(v_text, '|', v_char); +SELECT v_text; +END| +CALL p1(); +v_text +abc|def +DROP PROCEDURE p1; diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index c5d60446e0a..d2a958e8f0c 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -208,3 +208,17 @@ drop procedure bug10100pd| drop procedure bug10100pc| drop view v1| drop table t3| +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; +call 15298_1(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +call 15298_2(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 5ca185d6abc..dd96dc6d983 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1298,3 +1298,49 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2,t1; set @@sql_mode= @org_mode; +set @@sql_mode='traditional'; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +ERROR HY000: Too long comment for table 't1' +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +ERROR HY000: Too long comment for field 'i' +set @@sql_mode= @org_mode; +create table t1 +(i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +Warnings: +Warning 1105 Unknown error +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +column_name column_comment +i 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* +drop table t1; +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='123456789*123456789*123456789*123456789*123456789*123456789*' +drop table t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index cce8f8e5b7a..042ad178fc8 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -143,10 +143,6 @@ select extract(SECOND FROM "1999-01-02 10:11:12"); select extract(MONTH FROM "2001-02-00"); # -# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null -# -SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); # test EXTRACT QUARTER (Bug #18100) # @@ -162,7 +158,11 @@ SELECT EXTRACT(QUARTER FROM '2004-09-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-10-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-11-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-12-15') AS quarter; - +# +# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null +# +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); # # Test big intervals (Bug #3498) diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 73aea01dfa2..1db74634414 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -859,7 +859,40 @@ select concat(@a, table_name), @a, table_name from information_schema.tables where table_schema = 'test'; drop table t1,t2; -# End of 5.0 tests. +# +# Bug#20230: routine_definition is not null +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; + +connect (conn1, localhost, mysql_bug20230,,); + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; +CALL p1(); +SELECT f1(); + +disconnect conn1; +connection default; + +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; + +--echo End of 5.0 tests. # # Show engines # @@ -877,3 +910,5 @@ select user,db from information_schema.processlist; connection default; drop user user3148@localhost; +--echo End of 5.1 tests. + diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 73c612b203f..fde9f1479f8 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -389,6 +389,7 @@ drop index i1 on t1; --disable_warnings --exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables; +--exec rm $MYSQLTEST_VARDIR/master-data/test/tmp.dat || true --enable_warnings select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%'; diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 5056a7f9b91..d4e930f91ec 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1255,4 +1255,49 @@ insert into t1 values (1),(2); select * from t1 ORDER BY a DESC; drop table t1; +# +# Bug 20770 Partitions: DATA DIRECTORY clause change in reorganize +# doesn't remove old directory +# +--disable_query_log +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpdata || true +eval SET @data_dir = 'DATA DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpdata'''; +let $data_directory = `select @data_dir`; + +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpinx || true +eval SET @inx_dir = 'INDEX DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpinx'''; +let $inx_directory = `select @inx_dir`; +--enable_query_log + +--replace_result $MYSQLTEST_VARDIR "hello" +eval create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart00, SUBPARTITION subpart01)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test/t1* || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1* || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1* || true +--replace_result $MYSQLTEST_VARDIR "hello" + +eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart10, SUBPARTITION subpart11), + partition p2 VALUES LESS THAN (2) $data_directory $inx_directory + (SUBPARTITION subpart20, SUBPARTITION subpart21)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test/t1* || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1* || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1* || true + +drop table t1; +--exec rmdir $MYSQLTEST_VARDIR/master-data/tmpdata || true +--exec rmdir $MYSQLTEST_VARDIR/master-data/tmpinx || true --echo End of 5.1 tests diff --git a/mysql-test/t/partition_mgm.test b/mysql-test/t/partition_mgm.test index cfb76192de4..39512de154f 100644 --- a/mysql-test/t/partition_mgm.test +++ b/mysql-test/t/partition_mgm.test @@ -12,7 +12,21 @@ ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; --replace_result $MYSQLTEST_VARDIR "hello" --exec ls $MYSQLTEST_VARDIR/master-data/test/t1* +drop table t1; +# +# Bug 20767: REORGANIZE partition crashes +# +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), + partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), + partition p12 values in (3,4)); - +drop table t1; diff --git a/mysql-test/t/partition_order.test b/mysql-test/t/partition_order.test index 1e1b3339d64..ad956361d00 100644 --- a/mysql-test/t/partition_order.test +++ b/mysql-test/t/partition_order.test @@ -818,11 +818,27 @@ partitions 2 # Insert a couple of tuples INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); select * from t1 force index (b) where b < 10 OR b IS NULL order by b; - +select * from t1 force index (b) where b < 10 ORDER BY b; +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +drop table t1; + +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), + partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +select * from t1 where a = 1 order by b desc; drop table t1; diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 8e1e2e72e69..38142a9d485 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -555,3 +555,90 @@ reorganize partition p5 into drop table t1; +# +# New test cases for date based partitioning +# +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), + PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), + PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), + PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), + PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), + PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), + PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), + PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), + PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), + PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), + PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), + PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), + PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), + PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), + PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), + PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), + PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), + PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), + PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), + PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), + PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), + PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), + PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), + PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), + PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), + PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), + PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), + PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), + PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), + PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), + PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), + PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); + +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); + +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); + +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); + +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); + +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR + (a >= '2005-07-01' AND a <= '2005-09-30'); +EXPLAIN PARTITIONS SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR + (a >= '2005-07-01' AND a <= '2005-09-30'); +DROP TABLE t1; diff --git a/mysql-test/t/rpl_ndb_bank.test b/mysql-test/t/rpl_ndb_bank.test index 3601c841c54..d6a10e4ccac 100644 --- a/mysql-test/t/rpl_ndb_bank.test +++ b/mysql-test/t/rpl_ndb_bank.test @@ -121,6 +121,7 @@ RESET MASTER; CREATE TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; DELETE FROM cluster.backup_info; LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; +--exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 SELECT @the_backup_id:=backup_id FROM cluster.backup_info; let the_backup_id=`select @the_backup_id`; diff --git a/mysql-test/t/rpl_ndb_dd_advance.test b/mysql-test/t/rpl_ndb_dd_advance.test index 30d5deb47ad..1fe36ecd8a1 100644 --- a/mysql-test/t/rpl_ndb_dd_advance.test +++ b/mysql-test/t/rpl_ndb_dd_advance.test @@ -441,7 +441,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) DELETE FROM cluster.backup_info; LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; - +--exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 SELECT @the_backup_id:=backup_id FROM cluster.backup_info; diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test index 81504904797..48dbd4de7aa 100644 --- a/mysql-test/t/sp-vars.test +++ b/mysql-test/t/sp-vars.test @@ -1271,3 +1271,39 @@ SELECT f1(); # DROP FUNCTION f1; + + +# +# Bug#17226: Variable set in cursor on first iteration is assigned +# second iterations value +# +# The problem was in incorrect handling of local variables of type +# TEXT (BLOB). +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE v_char VARCHAR(255); + DECLARE v_text TEXT DEFAULT ''; + + SET v_char = 'abc'; + + SET v_text = v_char; + + SET v_char = 'def'; + + SET v_text = concat(v_text, '|', v_char); + + SELECT v_text; +END| +delimiter ;| + +CALL p1(); + +DROP PROCEDURE p1; + +# End of 5.0 tests. diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index 0adbeb2d98b..b087f699f86 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -265,3 +265,23 @@ drop view v1| drop table t3| delimiter ;| + +# +# Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context +# +--disable_warnings +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +--enable_warnings +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; + +connect (con1,localhost,mysqltest_1,,test); +call 15298_1(); +call 15298_2(); + +connection default; +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 212150e057c..f6a8824c841 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -1155,3 +1155,42 @@ create table t2 select date from t1; show create table t2; drop table t2,t1; set @@sql_mode= @org_mode; + +# +# Bug #13934 Silent truncation of table comments +# +set @@sql_mode='traditional'; +--error 1105 +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +--error 1105 +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +set @@sql_mode= @org_mode; +create table t1 +(i int comment + '123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); + +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +drop table t1; + +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +drop table t1; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3eab782d167..20d1e372a2c 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -674,9 +674,14 @@ void field_conv(Field *to,Field *from) { // Be sure the value is stored Field_blob *blob=(Field_blob*) to; from->val_str(&blob->value); - if (!blob->value.is_alloced() && - from->real_type() != MYSQL_TYPE_STRING && - from->real_type() != MYSQL_TYPE_VARCHAR) + /* + Copy value if copy_blobs is set, or source is not a string and + we have a pointer to its internal string conversion buffer. + */ + if (to->table->copy_blobs || + (!blob->value.is_alloced() && + from->real_type() != MYSQL_TYPE_STRING && + from->real_type() != MYSQL_TYPE_VARCHAR)) blob->value.copy(); blob->store(blob->value.ptr(),blob->value.length(),from->charset()); return; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2d097c34f97..2acc1f4ed7d 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1202,12 +1202,13 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key, int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len) { + DBUG_ENTER("ha_myisam::index_read_last"); DBUG_ASSERT(inited==INDEX); statistic_increment(table->in_use->status_var.ha_read_key_count, &LOCK_status); int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; - return error; + DBUG_RETURN(error); } int ha_myisam::index_next(byte * buf) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5b15c4b32bd..615c4bfb1bf 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -204,6 +204,7 @@ void ha_partition::init_handler_variables() m_name_buffer_ptr= NULL; m_engine_array= NULL; m_file= NULL; + m_file_tot_parts= 0; m_reorged_file= NULL; m_new_file= NULL; m_reorged_parts= 0; @@ -1125,13 +1126,15 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, int ha_partition::prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name) + handler *file, const char *part_name, + partition_element *p_elem) { int error; bool create_flag= FALSE; bool open_flag= FALSE; DBUG_ENTER("prepare_new_partition"); + set_up_table_before_create(table, part_name, create_info, 0, p_elem); if ((error= file->create(part_name, table, create_info))) goto error; create_flag= TRUE; @@ -1231,7 +1234,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, uint no_parts= m_part_info->partitions.elements; uint no_subparts= m_part_info->no_subparts; uint i= 0; - uint no_remain_partitions, part_count; + uint no_remain_partitions, part_count, orig_count; handler **new_file_array; int error= 1; bool first; @@ -1266,10 +1269,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, } while (++i < no_parts); } if (m_reorged_parts && - !(m_reorged_file= (handler**)sql_calloc(sizeof(partition_element*)* + !(m_reorged_file= (handler**)sql_calloc(sizeof(handler*)* (m_reorged_parts + 1)))) { - mem_alloc_error(sizeof(partition_element*)*(m_reorged_parts+1)); + mem_alloc_error(sizeof(handler*)*(m_reorged_parts+1)); DBUG_RETURN(ER_OUTOFMEMORY); } @@ -1340,6 +1343,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, ones used to be. */ first= FALSE; + DBUG_ASSERT(i + m_reorged_parts <= m_file_tot_parts); memcpy((void*)m_reorged_file, &m_file[i*no_subparts], sizeof(handler*)*m_reorged_parts*no_subparts); } @@ -1353,15 +1357,18 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, */ i= 0; part_count= 0; + orig_count= 0; part_it.rewind(); do { partition_element *part_elem= part_it++; if (part_elem->part_state == PART_NORMAL) { - memcpy((void*)&new_file_array[part_count], (void*)&m_file[i], + DBUG_ASSERT(orig_count + no_subparts <= m_file_tot_parts); + memcpy((void*)&new_file_array[part_count], (void*)&m_file[orig_count], sizeof(handler*)*no_subparts); part_count+= no_subparts; + orig_count+= no_subparts; } else if (part_elem->part_state == PART_CHANGED || part_elem->part_state == PART_TO_BE_ADDED) @@ -1420,7 +1427,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add subpartition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[part], - (const char *)part_name_buff))) + (const char *)part_name_buff, + sub_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1436,7 +1444,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], - (const char *)part_name_buff))) + (const char *)part_name_buff, + part_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1648,7 +1657,7 @@ uint ha_partition::del_ren_cre_table(const char *from, error= (*file)->delete_table((const char*) from_buff); else { - set_up_table_before_create(table_arg, from_buff, create_info, i); + set_up_table_before_create(table_arg, from_buff, create_info, i, NULL); error= (*file)->create(from_buff, table_arg, create_info); } name_buffer_ptr= strend(name_buffer_ptr) + 1; @@ -1724,12 +1733,15 @@ partition_element *ha_partition::find_partition_element(uint part_id) void ha_partition::set_up_table_before_create(TABLE *table, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id) + uint part_id, + partition_element *part_elem) { - partition_element *part_elem= find_partition_element(part_id); - if (!part_elem) - return; // Fatal error + { + part_elem= find_partition_element(part_id); + if (!part_elem) + return; // Fatal error + } table->s->max_rows= part_elem->part_max_rows; table->s->min_rows= part_elem->part_min_rows; const char *partition_name= strrchr(partition_name_with_path, FN_LIBCHAR); @@ -1959,6 +1971,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) if (!(m_file= (handler **) alloc_root(mem_root, alloc_len))) DBUG_RETURN(TRUE); + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); for (i= 0; i < m_tot_parts; i++) { @@ -2008,6 +2021,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root) mem_alloc_error(alloc_len); goto error_end; } + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); DBUG_ASSERT(m_part_info->no_parts > 0); @@ -2229,7 +2243,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_table_flags&= ~(HA_CAN_GEOMETRY | HA_CAN_FULLTEXT | HA_DUPLICATE_POS | HA_CAN_SQL_HANDLER | HA_CAN_INSERT_DELAYED); m_table_flags|= HA_FILE_BASED | HA_REC_NOT_IN_SEQ; - + key_used_on_scan= m_file[0]->key_used_on_scan; + implicit_emptied= m_file[0]->implicit_emptied; /* Add 2 bytes for partition id in position ref length. ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS @@ -3265,6 +3280,7 @@ int ha_partition::index_read(byte * buf, const byte * key, DBUG_ENTER("ha_partition::index_read"); end_range= 0; + m_index_scan_type= partition_index_read; DBUG_RETURN(common_index_read(buf, key, key_len, find_flag)); } @@ -3282,18 +3298,24 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, enum ha_rkey_function find_flag) { int error; + bool reverse_order= FALSE; DBUG_ENTER("ha_partition::common_index_read"); memcpy((void*)m_start_key.key, key, key_len); m_start_key.length= key_len; m_start_key.flag= find_flag; - m_index_scan_type= partition_index_read; if ((error= partition_scan_set_up(buf, TRUE))) { DBUG_RETURN(error); } - + if (find_flag == HA_READ_PREFIX_LAST || + find_flag == HA_READ_PREFIX_LAST_OR_PREV || + find_flag == HA_READ_BEFORE_KEY) + { + reverse_order= TRUE; + m_ordered_scan_ongoing= TRUE; + } if (!m_ordered_scan_ongoing || (find_flag == HA_READ_KEY_EXACT && (key_len >= m_curr_key_info->key_length || @@ -3319,7 +3341,7 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, In all other cases we will use the ordered index scan. This will use the partition set created by the get_partition_set method. */ - error= handle_ordered_index_scan(buf); + error= handle_ordered_index_scan(buf, reverse_order); } DBUG_RETURN(error); } @@ -3403,7 +3425,7 @@ int ha_partition::common_first_last(byte *buf) if (!m_ordered_scan_ongoing && m_index_scan_type != partition_index_last) return handle_unordered_scan_next_partition(buf); - return handle_ordered_index_scan(buf); + return handle_ordered_index_scan(buf, FALSE); } @@ -3457,7 +3479,9 @@ int ha_partition::index_read_last(byte *buf, const byte *key, uint keylen) DBUG_ENTER("ha_partition::index_read_last"); m_ordered= TRUE; // Safety measure - DBUG_RETURN(index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); + end_range= 0; + m_index_scan_type= partition_index_read_last; + DBUG_RETURN(common_index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); } @@ -3597,6 +3621,7 @@ int ha_partition::read_range_first(const key_range *start_key, } else { + m_index_scan_type= partition_index_read; error= common_index_read(m_rec0, start_key->key, start_key->length, start_key->flag); @@ -3855,12 +3880,11 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf) entries. */ -int ha_partition::handle_ordered_index_scan(byte *buf) +int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) { uint i; uint j= 0; bool found= FALSE; - bool reverse_order= FALSE; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); m_top_entry= NO_CURRENT_PART_ID; @@ -3881,7 +3905,6 @@ int ha_partition::handle_ordered_index_scan(byte *buf) m_start_key.key, m_start_key.length, m_start_key.flag); - reverse_order= FALSE; break; case partition_index_first: error= file->index_first(rec_buf_ptr); @@ -3891,6 +3914,12 @@ int ha_partition::handle_ordered_index_scan(byte *buf) error= file->index_last(rec_buf_ptr); reverse_order= TRUE; break; + case partition_index_read_last: + error= file->index_read_last(rec_buf_ptr, + m_start_key.key, + m_start_key.length); + reverse_order= TRUE; + break; default: DBUG_ASSERT(FALSE); DBUG_RETURN(HA_ERR_END_OF_FILE); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index f9fe5f2501f..c62f21cfaa1 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -46,7 +46,8 @@ private: partition_index_read= 0, partition_index_first= 1, partition_index_last= 2, - partition_no_index_scan= 3 + partition_index_read_last= 3, + partition_no_index_scan= 4 }; /* Data for the partition handler */ int m_mode; // Open mode @@ -55,6 +56,7 @@ private: char *m_name_buffer_ptr; // Pointer to first partition name handlerton **m_engine_array; // Array of types of the handlers handler **m_file; // Array of references to handler inst. + uint m_file_tot_parts; // Debug handler **m_new_file; // Array of references to new handlers handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors @@ -202,7 +204,8 @@ private: int copy_partitions(ulonglong *copied, ulonglong *deleted); void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name); + handler *file, const char *part_name, + partition_element *p_elem); /* delete_table, rename_table and create uses very similar logic which is packed into this routine. @@ -222,7 +225,8 @@ private: void set_up_table_before_create(TABLE *table_arg, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id); + uint part_id, + partition_element *p_elem); partition_element *find_partition_element(uint part_id); public: @@ -429,7 +433,7 @@ private: return (queue_buf(part_id) + PARTITION_BYTES_IN_POS); } - int handle_ordered_index_scan(byte * buf); + int handle_ordered_index_scan(byte * buf, bool reverse_order); int handle_ordered_next(byte * buf, bool next_same); int handle_ordered_prev(byte * buf); void return_top_record(byte * buf); diff --git a/sql/handler.h b/sql/handler.h index 3c090b887a3..b4572d449e5 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -725,7 +725,8 @@ typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; LEX_STRING connect_string; - const char *comment,*password, *tablespace; + const char *password, *tablespace; + LEX_STRING comment; const char *data_file_name, *index_file_name; const char *alias; ulonglong max_rows,min_rows; diff --git a/sql/item.cc b/sql/item.cc index eff2b744972..7d4eca07232 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1501,7 +1501,18 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, } - +void Item_ident_for_show::make_field(Send_field *tmp_field) +{ + tmp_field->table_name= tmp_field->org_table_name= table_name; + tmp_field->db_name= db_name; + tmp_field->col_name= tmp_field->org_col_name= field->field_name; + tmp_field->charsetnr= field->charset()->number; + tmp_field->length=field->field_length; + tmp_field->type=field->type(); + tmp_field->flags= field->table->maybe_null ? + (field->flags & ~NOT_NULL_FLAG) : field->flags; + tmp_field->decimals= 0; +} /**********************************************/ diff --git a/sql/item.h b/sql/item.h index 5494b885ff9..be25d51bea1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -890,13 +890,6 @@ protected: public: LEX_STRING m_name; - /* - Buffer, pointing to the string value of the item. We need it to - protect internal buffer from changes. See comment to analogous - member in Item_param for more details. - */ - String str_value_ptr; - public: #ifndef DBUG_OFF /* @@ -1206,6 +1199,28 @@ public: bool any_privileges); }; + +class Item_ident_for_show :public Item +{ +public: + Field *field; + const char *db_name; + const char *table_name; + + Item_ident_for_show(Field *par_field, const char *db_arg, + const char *table_name_arg) + :field(par_field), db_name(db_arg), table_name(table_name_arg) + {} + + enum Type type() const { return FIELD_ITEM; } + double val_real() { return field->val_real(); } + longlong val_int() { return field->val_int(); } + String *val_str(String *str) { return field->val_str(str); } + my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); } + void make_field(Send_field *tmp_field); +}; + + class Item_equal; class COND_EQUAL; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 55958bae061..08b7467eafb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -555,6 +555,7 @@ int append_query_string(CHARSET_INFO *csinfo, void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); +LEX_USER *get_current_user(THD *thd, LEX_USER *user); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 029c6fa22a9..8368e828fdc 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1933,8 +1933,11 @@ sp_head::show_create_procedure(THD *thd) field_list.push_back(new Item_empty_string("Procedure", NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); // 1024 is for not to confuse old clients - field_list.push_back(new Item_empty_string("Create Procedure", - max(buffer.length(), 1024))); + Item_empty_string *definition= + new Item_empty_string("Create Procedure", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -1943,6 +1946,8 @@ sp_head::show_create_procedure(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); @@ -1998,8 +2003,11 @@ sp_head::show_create_function(THD *thd) &sql_mode_len); field_list.push_back(new Item_empty_string("Function",NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); - field_list.push_back(new Item_empty_string("Create Function", - max(buffer.length(),1024))); + Item_empty_string *definition= + new Item_empty_string("Create Function", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -2008,6 +2016,8 @@ sp_head::show_create_function(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e82ad611427..2d5b9d98061 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2906,7 +2906,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, { ulong column_priv= 0; List_iterator str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[3]; bool create_new_users=0; char *db_name, *table_name; @@ -3032,10 +3032,15 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, thd->mem_root= &memex; grant_version++; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { int error; GRANT_TABLE *grant_table; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3171,7 +3176,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, bool revoke_grant, bool no_error) { List_iterator str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[2]; bool create_new_users=0, result=0; char *db_name, *table_name; @@ -3239,10 +3244,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, DBUG_PRINT("info",("now time to iterate and add users")); - while ((Str= str_list++)) + while ((tmp_Str= str_list++)) { int error; GRANT_NAME *grant_name; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3311,7 +3321,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, ulong rights, bool revoke_grant) { List_iterator str_list (list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; char tmp_db[NAME_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; @@ -3370,8 +3380,13 @@ bool mysql_grant(THD *thd, const char *db, List &list, grant_version++; int result=0; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -5334,7 +5349,7 @@ bool mysql_create_user(THD *thd, List &list) int result; String wrong_users; ulong sql_mode; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_create_user"); @@ -5346,8 +5361,13 @@ bool mysql_create_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -5393,7 +5413,7 @@ bool mysql_drop_user(THD *thd, List &list) { int result; String wrong_users; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_drop_user"); @@ -5405,8 +5425,14 @@ bool mysql_drop_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + user_name= get_current_user(thd, tmp_user_name); + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5443,8 +5469,8 @@ bool mysql_rename_user(THD *thd, List &list) { int result; String wrong_users; - LEX_USER *user_from; - LEX_USER *user_to; + LEX_USER *user_from, *tmp_user_from; + LEX_USER *user_to, *tmp_user_to; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_rename_user"); @@ -5456,9 +5482,19 @@ bool mysql_rename_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_from= user_list++)) + while ((tmp_user_from= user_list++)) { - user_to= user_list++; + if (!(user_from= get_current_user(thd, tmp_user_from))) + { + result= TRUE; + continue; + } + tmp_user_to= user_list++; + if (!(user_to= get_current_user(thd, tmp_user_to))) + { + result= TRUE; + continue; + } DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ /* @@ -5513,10 +5549,15 @@ bool mysql_revoke_all(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - LEX_USER *lex_user; + LEX_USER *lex_user, *tmp_lex_user; List_iterator user_list(list); - while ((lex_user=user_list++)) + while ((tmp_lex_user= user_list++)) { + if (!(lex_user= get_current_user(thd, tmp_lex_user))) + { + result= -1; + continue; + } if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE)) { sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not " diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ecc0bb6aad7..fe36b578f3b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -42,8 +42,6 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01; #define yySkip() lex->ptr++ #define yyLength() ((uint) (lex->ptr - lex->tok_start)-1) -pthread_key(LEX*,THR_LEX); - /* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 @@ -92,8 +90,6 @@ void lex_init(void) for (i=0 ; i < array_elements(sql_functions) ; i++) sql_functions[i].length=(uchar) strlen(sql_functions[i].name); - VOID(pthread_key_create(&THR_LEX,NULL)); - DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3242e20f857..85264638551 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1191,8 +1191,4 @@ extern void lex_start(THD *thd, const uchar *buf, uint length); extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); -extern pthread_key(LEX*,THR_LEX); - -#define current_lex (current_thd->lex) - -#endif +#endif /* MYSQL_SERVER */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 16136373002..b86dfa91a15 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2431,7 +2431,7 @@ static void reset_one_shot_variables(THD *thd) /* - Execute command saved in thd and current_lex->sql_command + Execute command saved in thd and lex->sql_command SYNOPSIS mysql_execute_command() @@ -4070,11 +4070,13 @@ end_with_restore_list: if (thd->security_ctx->user) // If not replication { - LEX_USER *user; + LEX_USER *user, *tmp_user; List_iterator user_list(lex->users_list); - while ((user= user_list++)) + while ((tmp_user= user_list++)) { + if (!(user= get_current_user(thd, tmp_user))) + goto error; if (specialflag & SPECIAL_NO_RESOLVE && hostname_requires_resolving(user->host.str)) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -4156,9 +4158,13 @@ end_with_restore_list: if (lex->sql_command == SQLCOM_GRANT) { List_iterator str_list(lex->users_list); - LEX_USER *user; - while ((user=str_list++)) + LEX_USER *user, *tmp_user; + while ((tmp_user=str_list++)) + { + if (!(user= get_current_user(thd, tmp_user))) + goto error; reset_mqh(user); + } } } } @@ -4213,13 +4219,18 @@ end_with_restore_list: } #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: + { + LEX_USER *grant_user= get_current_user(thd, lex->grant_user); + if (!grant_user) + goto error; if ((thd->security_ctx->priv_user && - !strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) || + !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) { - res = mysql_show_grants(thd,lex->grant_user); + res = mysql_show_grants(thd, grant_user); } break; + } #endif case SQLCOM_HA_OPEN: DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -5780,7 +5791,7 @@ bool check_stack_overrun(THD *thd, long margin, bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { - LEX *lex=current_lex; + LEX *lex= current_thd->lex; ulong old_info=0; if ((uint) *yystacksize >= MY_YACC_MAX) return 1; @@ -6245,7 +6256,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, void store_position_for_column(const char *name) { - current_lex->last_field->after=my_const_cast(char*) (name); + current_thd->lex->last_field->after=my_const_cast(char*) (name); } bool @@ -7788,3 +7799,34 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } + + +/* + Retuns information about user or current user. + + SYNOPSIS + get_current_user() + thd [in] thread handler + user [in] user + + RETURN + On success, return a valid pointer to initialized + LEX_USER, which contains user information. + On error, return 0. +*/ + +LEX_USER *get_current_user(THD *thd, LEX_USER *user) +{ + LEX_USER *curr_user; + if (!user->user.str) // current_user + { + if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); + return 0; + } + get_default_definer(thd, curr_user); + return curr_user; + } + return user; +} diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6018524456b..cb3027e32fa 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -770,7 +770,14 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) { if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) - field_list.push_back(new Item_field(field)); + { + if (table_list->view) + field_list.push_back(new Item_ident_for_show(field, + table_list->view_db.str, + table_list->view_name.str)); + else + field_list.push_back(new Item_field(field)); + } } restore_record(table, s->default_values); // Get empty record table->use_all_columns(); @@ -1345,10 +1352,10 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(buff, (uint) (end - buff)); } table->file->append_create_info(packet); - if (share->comment && share->comment[0]) + if (share->comment.length) { packet->append(STRING_WITH_LEN(" COMMENT=")); - append_unescaped(packet, share->comment, strlen(share->comment)); + append_unescaped(packet, share->comment.str, share->comment.length); } if (share->connect_string.length) { @@ -2901,11 +2908,14 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, (uint) (ptr-option_buff)-1), cs); { char *comment; - comment= show_table->file->update_table_comment(share->comment); + comment= show_table->file->update_table_comment(share->comment.str); if (comment) { - table->field[20]->store(comment, strlen(comment), cs); - if (comment != share->comment) + table->field[20]->store(comment, + (comment == share->comment.str ? + share->comment.length : + strlen(comment)), cs); + if (comment != share->comment.str) my_free(comment, MYF(0)); } } @@ -3330,6 +3340,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, { get_field(thd->mem_root, proc_table->field[10], &tmp_string); table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[7]->set_notnull(); } table->field[6]->store(STRING_WITH_LEN("SQL"), cs); table->field[10]->store(STRING_WITH_LEN("SQL"), cs); @@ -5283,7 +5294,7 @@ ST_FIELD_INFO proc_fields_info[]= {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, - {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0}, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ccddefab421..5dd60f87c46 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5479,8 +5479,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } create_info->db_type=new_db_type; - if (!create_info->comment) - create_info->comment= table->s->comment; + if (!create_info->comment.str) + { + create_info->comment.str= table->s->comment.str; + create_info->comment.length= table->s->comment.length; + } table->file->update_create_info(create_info); if ((create_info->table_options & diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8ce5bbc87aa..3fa536b99ae 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3734,14 +3734,15 @@ sub_part_definition: { LEX *lex= Lex; partition_info *part_info= lex->part_info; - partition_element *p_elem= new partition_element(); - if (!p_elem || - part_info->current_partition->subpartitions.push_back(p_elem)) + partition_element *curr_part= part_info->current_partition; + partition_element *sub_p_elem= new partition_element(curr_part); + if (!sub_p_elem || + curr_part->subpartitions.push_back(sub_p_elem)) { mem_alloc_error(sizeof(partition_element)); YYABORT; } - part_info->curr_part_elem= p_elem; + part_info->curr_part_elem= sub_p_elem; part_info->use_default_subpartitions= FALSE; part_info->use_default_no_subpartitions= FALSE; part_info->count_curr_subparts++; @@ -3879,7 +3880,7 @@ create_table_option: | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; } - | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } + | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} | PACK_KEYS_SYM opt_equal ulong_num { @@ -8352,24 +8353,10 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_GRANTS; - THD *thd= lex->thd; - Security_context *sctx= thd->security_ctx; LEX_USER *curr_user; - if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user)))) YYABORT; - curr_user->user.str= sctx->priv_user; - curr_user->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - curr_user->host.str= sctx->priv_host; - curr_user->host.length= strlen(sctx->priv_host); - } - else - { - curr_user->host.str= (char *) "%"; - curr_user->host.length= 1; - } - curr_user->password=null_lex_str; + bzero(curr_user, sizeof(st_lex_user)); lex->grant_user= curr_user; } | GRANTS FOR_SYM user @@ -9316,22 +9303,14 @@ user: } | CURRENT_USER optional_braces { - THD *thd= YYTHD; - Security_context *sctx= thd->security_ctx; - if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) YYABORT; - $$->user.str= sctx->priv_user; - $$->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - $$->host.str= sctx->priv_host; - $$->host.length= strlen(sctx->priv_host); - } - else - { - $$->host.str= (char *) "%"; - $$->host.length= 1; - } + /* + empty LEX_USER means current_user and + will be handled in the get_current_user() function + later + */ + bzero($$, sizeof(LEX_USER)); }; /* Keyword that we allow for identifiers (except SP labels) */ diff --git a/sql/table.cc b/sql/table.cc index 163f2a4f0b8..4c035f23fe6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -743,7 +743,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, int_length= uint2korr(head+274); share->null_fields= uint2korr(head+282); com_length= uint2korr(head+284); - share->comment= strdup_root(&share->mem_root, (char*) head+47); + share->comment.length= (int) (head[46]); + share->comment.str= strmake_root(&share->mem_root, (char*) head+47, + share->comment.length); DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length)); diff --git a/sql/table.h b/sql/table.h index 067c9d15887..f79d259ea5c 100644 --- a/sql/table.h +++ b/sql/table.h @@ -134,7 +134,7 @@ typedef struct st_table_share uint *blob_field; /* Index to blobs in Field arrray*/ byte *default_values; /* row with default values */ - char *comment; /* Comment about table */ + LEX_STRING comment; /* Comment about table */ CHARSET_INFO *table_charset; /* Default charset of string fields */ MY_BITMAP all_set; diff --git a/sql/unireg.cc b/sql/unireg.cc index 426debab7d8..396ff4fba27 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -76,7 +76,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, handler *db_file) { LEX_STRING str_db_type; - uint reclength,info_length,screens,key_info_length,maxlength,i; + uint reclength, info_length, screens, key_info_length, maxlength, tmp_len, i; ulong key_buff_length; File file; ulong filepos, data_offset; @@ -169,10 +169,30 @@ bool mysql_create_frm(THD *thd, const char *file_name, fileinfo[26]= (uchar) test((create_info->max_rows == 1) && (create_info->min_rows == 1) && (keys == 0)); int2store(fileinfo+28,key_info_length); - strmake((char*) forminfo+47,create_info->comment ? create_info->comment : "", - 60); - forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment + tmp_len= system_charset_info->cset->charpos(system_charset_info, + create_info->comment.str, + create_info->comment.str + + create_info->comment.length, 60); + if (tmp_len < create_info->comment.length) + { + char buff[128]; + (void) my_snprintf(buff, sizeof(buff), "Too long comment for table '%s'", + table); + if ((thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + goto err; + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + create_info->comment.length= tmp_len; + } + + strmake((char*) forminfo+47, create_info->comment.str ? + create_info->comment.str : "", create_info->comment.length); + forminfo[46]=(uchar) create_info->comment.length; #ifdef WITH_PARTITION_STORAGE_ENGINE if (part_info) { @@ -181,6 +201,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, } #endif int2store(fileinfo+59,db_file->extra_rec_buf_length()); + if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) || my_pwrite(file,(byte*) keybuff,key_info_length, (ulong) uint2korr(fileinfo+6),MYF_RW)) @@ -523,6 +544,27 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, create_field *field; while ((field=it++)) { + + uint tmp_len= system_charset_info->cset->charpos(system_charset_info, + field->comment.str, + field->comment.str + + field->comment.length, 255); + if (tmp_len < field->comment.length) + { + char buff[128]; + (void) my_snprintf(buff,sizeof(buff), "Too long comment for field '%s'", + field->field_name); + if ((current_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + DBUG_RETURN(1); + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + field->comment.length= tmp_len; + } + totlength+= field->length; com_length+= field->comment.length; if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY || diff --git a/storage/ndb/src/kernel/error/TimeModule.cpp b/storage/ndb/src/kernel/error/TimeModule.cpp index 4bd8e3daf99..c4e569e7221 100644 --- a/storage/ndb/src/kernel/error/TimeModule.cpp +++ b/storage/ndb/src/kernel/error/TimeModule.cpp @@ -22,7 +22,7 @@ static const char* cMonth[] = { "x", "January", "February", "Mars", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; -static const char* cDay[] = { "x", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", +static const char* cDay[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; static const char* cHour[] = { "00","01","02","03","04","05","06","07","08","09","10","11","12", diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 6f9b025222c..44f4b770b05 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -485,7 +485,8 @@ BackupRestore::object(Uint32 type, const void * ptr) if (ret) { NdbError errobj= dict->getNdbError(); - info << "FAILED " << errobj << endl; + info << "FAILED" << endl; + err << "Create tablespace failed: " << old.getName() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -523,7 +524,8 @@ BackupRestore::object(Uint32 type, const void * ptr) if (ret) { NdbError errobj= dict->getNdbError(); - info << "FAILED" << errobj << endl; + info << "FAILED" << endl; + err << "Create logfile group failed: " << old.getName() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -564,7 +566,9 @@ BackupRestore::object(Uint32 type, const void * ptr) info << "Creating datafile \"" << old.getPath() << "\"..." << flush; if (dict->createDatafile(old)) { - info << "FAILED " << dict->getNdbError() << endl; + NdbError errobj= dict->getNdbError(); + info << "FAILED" << endl; + err << "Create datafile failed: " << old.getPath() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -588,7 +592,9 @@ BackupRestore::object(Uint32 type, const void * ptr) info << "Creating undofile \"" << old.getPath() << "\"..." << flush; if (dict->createUndofile(old)) { - info << "FAILED " << dict->getNdbError() << endl; + NdbError errobj= dict->getNdbError(); + info << "FAILED" << endl; + err << "Create undofile failed: " << old.getPath() << ": " << errobj << endl; return false; } info << "done" << endl; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index d0b7d22ca24..8c010ee3728 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8311,6 +8311,39 @@ static void test_list_fields() } +static void test_bug19671() +{ + MYSQL_RES *result; + int rc; + myheader("test_bug19671"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + + rc= mysql_query(mysql, "drop view if exists v1"); + myquery(rc); + + rc= mysql_query(mysql, "create table t1(f1 int)"); + myquery(rc); + + rc= mysql_query(mysql, "create view v1 as select va.* from t1 va"); + myquery(rc); + + result= mysql_list_fields(mysql, "v1", NULL); + mytest(result); + + rc= my_process_result_set(result); + DIE_UNLESS(rc == 0); + + verify_prepare_field(result, 0, "f1", "f1", MYSQL_TYPE_LONG, + "v1", "v1", current_db, 11, "0"); + + mysql_free_result(result); + myquery(mysql_query(mysql, "drop view v1")); + myquery(mysql_query(mysql, "drop table t1")); +} + + /* Test a memory ovverun bug */ static void test_mem_overun() @@ -15455,6 +15488,7 @@ static struct my_tests_st my_tests[]= { { "test_bug14169", test_bug14169 }, { "test_bug17667", test_bug17667 }, { "test_mysql_insert_id", test_mysql_insert_id }, + { "test_bug19671", test_bug19671}, { 0, 0 } };