diff --git a/include/my_sys.h b/include/my_sys.h index 7c69a626366..ce785b58da4 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -206,11 +206,13 @@ void __CDECL hfree(void *ptr); #endif #endif /* MSDOS */ +#ifndef errno /* did we already get it? */ #ifdef HAVE_ERRNO_AS_DEFINE #include /* errno is a define */ #else extern int errno; /* declare errno */ #endif +#endif /* #ifndef errno */ extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE]; extern char *home_dir; /* Home directory for user */ extern char *my_progname; /* program-name (printed in errors) */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index b2f97492e70..210739b26fd 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -568,7 +568,14 @@ open_or_create_log_file( files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL, OS_LOG_FILE, &ret); if (ret == FALSE) { - if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS) { + if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS +#ifdef UNIV_AIX + /* AIX 5.1 after security patch ML7 may have errno set + to 0 here, which causes our function to return 100; + work around that AIX problem */ + && os_file_get_last_error(FALSE) != 100 +#endif + ) { fprintf(stderr, "InnoDB: Error in creating or opening %s\n", name); @@ -728,7 +735,14 @@ open_or_create_data_files( OS_FILE_NORMAL, OS_DATA_FILE, &ret); if (ret == FALSE && os_file_get_last_error(FALSE) != - OS_FILE_ALREADY_EXISTS) { + OS_FILE_ALREADY_EXISTS +#ifdef UNIV_AIX + /* AIX 5.1 after security patch ML7 may have + errno set to 0 here, which causes our function + to return 100; work around that AIX problem */ + && os_file_get_last_error(FALSE) != 100 +#endif + ) { fprintf(stderr, "InnoDB: Error in creating or opening %s\n", name); diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index a749d2bd4d1..6bcd0715ccd 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -45,7 +45,8 @@ mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ $(distdir)/std_data - $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.disabled $(distdir)/t + $(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t + -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.result.es $(srcdir)/r/*.require $(distdir)/r @@ -63,7 +64,7 @@ install-data-local: $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) $(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t - $(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t + -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t diff --git a/mysql-test/include/have_cp1250_ch.inc b/mysql-test/include/have_cp1250_ch.inc new file mode 100644 index 00000000000..eec5d69fbd6 --- /dev/null +++ b/mysql-test/include/have_cp1250_ch.inc @@ -0,0 +1,4 @@ +-- require r/have_cp1250_ch.require +disable_query_log; +show collation like "cp1250_czech_cs"; +enable_query_log; diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index 4268b121b1d..50e99e3ecd7 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -87,3 +87,42 @@ drop table t1; SELECT '0x8000000000000001'+0; '0x8000000000000001'+0 0 +create table t1 ( +value64 bigint unsigned not null, +value32 integer not null, +primary key(value64, value32) +); +create table t2 ( +value64 bigint unsigned not null, +value32 integer not null, +primary key(value64, value32) +); +insert into t1 values(17156792991891826145, 1); +insert into t1 values( 9223372036854775807, 2); +insert into t2 values(17156792991891826145, 3); +insert into t2 values( 9223372036854775807, 4); +select * from t1; +value64 value32 +9223372036854775807 2 +17156792991891826145 1 +select * from t2; +value64 value32 +9223372036854775807 4 +17156792991891826145 3 +select * from t1, t2 where t1.value64=17156792991891826145 and +t2.value64=17156792991891826145; +value64 value32 value64 value32 +17156792991891826145 1 17156792991891826145 3 +select * from t1, t2 where t1.value64=17156792991891826145 and +t2.value64=t1.value64; +value64 value32 value64 value32 +17156792991891826145 1 17156792991891826145 3 +select * from t1, t2 where t1.value64= 9223372036854775807 and +t2.value64=9223372036854775807; +value64 value32 value64 value32 +9223372036854775807 2 9223372036854775807 4 +select * from t1, t2 where t1.value64= 9223372036854775807 and +t2.value64=t1.value64; +value64 value32 value64 value32 +9223372036854775807 2 9223372036854775807 4 +drop table t1, t2; diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result new file mode 100644 index 00000000000..62936b84caf --- /dev/null +++ b/mysql-test/r/ctype_cp1250_ch.result @@ -0,0 +1,9 @@ +SHOW COLLATION LIKE 'cp1250_czech_cs'; +Collation Charset Id Default Compiled Sortlen +cp1250_czech_cs cp1250 34 Yes 2 +CREATE TABLE t1 (a char(16)) character set cp1250 collate cp1250_czech_cs; +INSERT INTO t1 VALUES (''); +SELECT a, length(a), a='', a=' ', a=' ' FROM t1; +a length(a) a='' a=' ' a=' ' + 0 1 1 1 +DROP TABLE t1; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 0779e2adfa2..821f67536f3 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -233,3 +233,20 @@ drop user mysqltest_B@'%'; ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' drop user mysqltest_B@'%'; drop user mysqltest_3@localhost; +set @@sql_mode=''; +create database mysqltest_1; +create table mysqltest_1.t1 (i int); +insert into mysqltest_1.t1 values (1),(2),(3); +GRANT ALL ON mysqltest_1.t1 TO mysqltest_1@'127.0.0.0/255.0.0.0'; +show grants for current_user(); +Grants for mysqltest_1@127.0.0.0/255.0.0.0 +GRANT USAGE ON *.* TO 'mysqltest_1'@'127.0.0.0/255.0.0.0' +GRANT ALL PRIVILEGES ON `mysqltest_1`.`t1` TO 'mysqltest_1'@'127.0.0.0/255.0.0.0' +select * from t1; +i +1 +2 +3 +REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0'; +drop table mysqltest_1.t1; +drop database mysqltest_1; diff --git a/mysql-test/r/have_cp1250_ch.require b/mysql-test/r/have_cp1250_ch.require new file mode 100644 index 00000000000..2eb834d97e2 --- /dev/null +++ b/mysql-test/r/have_cp1250_ch.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +cp1250_czech_cs cp1250 34 Yes 2 diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 121de940560..8e49a3df4c8 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -631,3 +631,10 @@ TABLES UPDATE_TIME datetime TABLES CHECK_TIME datetime ROUTINES CREATED datetime ROUTINES LAST_ALTERED datetime +SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A +WHERE NOT EXISTS +(SELECT * FROM INFORMATION_SCHEMA.COLUMNS B +WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA +AND A.TABLE_NAME = B.TABLE_NAME); +COUNT(*) +0 diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index d8d9e60acd1..17c0f32d666 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -477,27 +477,6 @@ CREATE TABLE `t1` ( ) TYPE=MyISAM; -/*!40000 ALTER TABLE `t1` DISABLE KEYS */; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES (''); -UNLOCK TABLES; -/*!40000 ALTER TABLE `t1` ENABLE KEYS */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` char(10) default NULL -) TYPE=MyISAM; - - /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; INSERT INTO `t1` VALUES (''); diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 7d008c6e753..5b638fd58ab 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -487,3 +487,40 @@ insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; ERROR 42000: FUNCTION test.char_length does not exist drop table t1; +prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0"; +execute stmt; +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +2 +execute stmt; +foo +SELECT FOUND_ROWS(); +FOUND_ROWS() +2 +deallocate prepare stmt; +create table t1 (a char(3) not null, b char(3) not null, +c char(3) not null, primary key (a, b, c)); +create table t2 like t1; +prepare stmt from +"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b) + where t1.a=1"; +execute stmt; +a +execute stmt; +a +execute stmt; +a +prepare stmt from +"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from +(t1 left outer join t2 on t2.a=? and t1.b=t2.b) +left outer join t2 t3 on t3.a=? where t1.a=?"; +set @a:=1, @b:=1, @c:=1; +execute stmt using @a, @b, @c; +a b c a b c +execute stmt using @a, @b, @c; +a b c a b c +execute stmt using @a, @b, @c; +a b c a b c +deallocate prepare stmt; +drop table t1,t2; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 24045bae430..803cb89cecf 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2542,3 +2542,41 @@ drop procedure bug7992| drop table t3| drop table t1; drop table t2; +CREATE TABLE t1 ( +lpitnumber int(11) default NULL, +lrecordtype int(11) default NULL +); +CREATE TABLE t2 ( +lbsiid int(11) NOT NULL default '0', +ltradingmodeid int(11) NOT NULL default '0', +ltradingareaid int(11) NOT NULL default '0', +csellingprice decimal(19,4) default NULL, +PRIMARY KEY (lbsiid,ltradingmodeid,ltradingareaid) +); +CREATE TABLE t3 ( +lbsiid int(11) NOT NULL default '0', +ltradingareaid int(11) NOT NULL default '0', +PRIMARY KEY (lbsiid,ltradingareaid) +); +CREATE PROCEDURE bug8849() +begin +insert into t3 +( +t3.lbsiid, +t3.ltradingareaid +) +select distinct t1.lpitnumber, t2.ltradingareaid +from +t2 join t1 on +t1.lpitnumber = t2.lbsiid +and t1.lrecordtype = 1 +left join t2 as price01 on +price01.lbsiid = t2.lbsiid and +price01.ltradingmodeid = 1 and +t2.ltradingareaid = price01.ltradingareaid; +end| +call bug8849(); +call bug8849(); +call bug8849(); +drop procedure bug8849; +drop tables t1,t2,t3; diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 8aa20a88177..b36020bc2a3 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -93,3 +93,15 @@ t1 CREATE TABLE `t1` ( `b` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index c509a4113f4..a26b78254e7 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -71,3 +71,36 @@ drop table t1; # atof() behaviour is different of different systems. to be fixed in 4.1 SELECT '0x8000000000000001'+0; +# Test for BUG#8562: joins over BIGINT UNSIGNED value + constant propagation +create table t1 ( + value64 bigint unsigned not null, + value32 integer not null, + primary key(value64, value32) +); + +create table t2 ( + value64 bigint unsigned not null, + value32 integer not null, + primary key(value64, value32) +); + +insert into t1 values(17156792991891826145, 1); +insert into t1 values( 9223372036854775807, 2); +insert into t2 values(17156792991891826145, 3); +insert into t2 values( 9223372036854775807, 4); + +select * from t1; +select * from t2; + +select * from t1, t2 where t1.value64=17156792991891826145 and +t2.value64=17156792991891826145; +select * from t1, t2 where t1.value64=17156792991891826145 and +t2.value64=t1.value64; + +select * from t1, t2 where t1.value64= 9223372036854775807 and +t2.value64=9223372036854775807; +select * from t1, t2 where t1.value64= 9223372036854775807 and +t2.value64=t1.value64; + +drop table t1, t2; + diff --git a/mysql-test/t/ctype_cp1250_ch.test b/mysql-test/t/ctype_cp1250_ch.test new file mode 100644 index 00000000000..06aea7b9979 --- /dev/null +++ b/mysql-test/t/ctype_cp1250_ch.test @@ -0,0 +1,12 @@ +-- source include/have_cp1250_ch.inc + +SHOW COLLATION LIKE 'cp1250_czech_cs'; + +# +# Bugs: #8840: Empty string comparison and character set 'cp1250' +# + +CREATE TABLE t1 (a char(16)) character set cp1250 collate cp1250_czech_cs; +INSERT INTO t1 VALUES (''); +SELECT a, length(a), a='', a=' ', a=' ' FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index d0778d4c082..3b1200f8a6e 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -246,3 +246,18 @@ connection default; drop user mysqltest_B@'%'; drop user mysqltest_3@localhost; # +# Bug #3309: Test IP addresses with netmask +set @@sql_mode=''; +create database mysqltest_1; +create table mysqltest_1.t1 (i int); +insert into mysqltest_1.t1 values (1),(2),(3); +GRANT ALL ON mysqltest_1.t1 TO mysqltest_1@'127.0.0.0/255.0.0.0'; +connect (n1,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,$MASTER_MYSOCK); +connection n1; +show grants for current_user(); +select * from t1; +disconnect n1; +connection default; +REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0'; +drop table mysqltest_1.t1; +drop database mysqltest_1; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 86d7bad76bc..9ff0b1fdf61 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -400,3 +400,12 @@ information_schema.columns where data_type = 'longtext'; select table_name, column_name, data_type from information_schema.columns where data_type = 'datetime'; + +# +# Bug #8164 subquery with INFORMATION_SCHEMA.COLUMNS, 100 % CPU +# +SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A +WHERE NOT EXISTS +(SELECT * FROM INFORMATION_SCHEMA.COLUMNS B + WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA + AND A.TABLE_NAME = B.TABLE_NAME); diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 3f19c7f0c52..43599e3b3a9 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -158,7 +158,14 @@ drop database mysqldump_test_db; CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 ''); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 ---exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1 +# +# Bug#8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# +#--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 --default-character-set=cp850 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=cp850 --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test t1 diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 7f65a7b04da..1af84119b79 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -497,3 +497,46 @@ insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; drop table t1; +# +# Bug #6089: FOUND_ROWS returns wrong values when no table/view is used +# + +prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0"; +execute stmt; +SELECT FOUND_ROWS(); +execute stmt; +SELECT FOUND_ROWS(); +deallocate prepare stmt; + +# +# Bug#8115: equality propagation and prepared statements +# + +create table t1 (a char(3) not null, b char(3) not null, + c char(3) not null, primary key (a, b, c)); +create table t2 like t1; + +# reduced query +prepare stmt from + "select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b) + where t1.a=1"; +execute stmt; +execute stmt; +execute stmt; + +# original query +prepare stmt from +"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from +(t1 left outer join t2 on t2.a=? and t1.b=t2.b) +left outer join t2 t3 on t3.a=? where t1.a=?"; + +set @a:=1, @b:=1, @c:=1; + +execute stmt using @a, @b, @c; +execute stmt using @a, @b, @c; +execute stmt using @a, @b, @c; + +deallocate prepare stmt; + +drop table t1,t2; + diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 439ace881d1..69bdeb7a059 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3086,3 +3086,52 @@ delimiter ;| drop table t1; drop table t2; +# +# Bug#8849: rolling back changes to AND/OR structure of ON and WHERE clauses +# in SP +# + +CREATE TABLE t1 ( + lpitnumber int(11) default NULL, + lrecordtype int(11) default NULL +); + +CREATE TABLE t2 ( + lbsiid int(11) NOT NULL default '0', + ltradingmodeid int(11) NOT NULL default '0', + ltradingareaid int(11) NOT NULL default '0', + csellingprice decimal(19,4) default NULL, + PRIMARY KEY (lbsiid,ltradingmodeid,ltradingareaid) +); + +CREATE TABLE t3 ( + lbsiid int(11) NOT NULL default '0', + ltradingareaid int(11) NOT NULL default '0', + PRIMARY KEY (lbsiid,ltradingareaid) +); + +delimiter |; +CREATE PROCEDURE bug8849() +begin + insert into t3 + ( + t3.lbsiid, + t3.ltradingareaid + ) + select distinct t1.lpitnumber, t2.ltradingareaid + from + t2 join t1 on + t1.lpitnumber = t2.lbsiid + and t1.lrecordtype = 1 + left join t2 as price01 on + price01.lbsiid = t2.lbsiid and + price01.ltradingmodeid = 1 and + t2.ltradingareaid = price01.ltradingareaid; +end| +delimiter ;| + +call bug8849(); +call bug8849(); +call bug8849(); +drop procedure bug8849; +drop tables t1,t2,t3; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 7fb7e81b3b1..f477fc378c6 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -121,3 +121,18 @@ eval alter table t1 index directory="$MYSQL_TEST_DIR/var/log"; enable_query_log; show create table t1; drop table t1; + +# +# Test specifying DATA DIRECTORY that is the same as what would normally +# have been chosen. (Bug #8707) +# +disable_query_log; +eval create table t1 (i int) data directory = "$MYSQL_TEST_DIR/var/master-data/test/"; +enable_query_log; +show create table t1; +drop table t1; +disable_query_log; +eval create table t1 (i int) index directory = "$MYSQL_TEST_DIR/var/master-data/test/"; +enable_query_log; +show create table t1; +drop table t1; diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 913f632fbb4..80dca7d56ac 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -32,6 +32,7 @@ File my_create_with_symlink(const char *linkname, const char *filename, int tmp_errno; /* Test if we should create a link */ int create_link; + char abs_linkname[FN_REFLEN]; DBUG_ENTER("my_create_with_symlink"); if (my_disable_symlinks) @@ -42,7 +43,11 @@ File my_create_with_symlink(const char *linkname, const char *filename, filename= linkname; } else - create_link= (linkname && strcmp(linkname,filename)); + { + if (linkname) + my_realpath(&abs_linkname, linkname, MYF(0)); + create_link= (linkname && strcmp(abs_linkname,filename)); + } if (!(MyFlags & MY_DELETE_OLD)) { diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 6325f659e39..17d55176830 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -5344,7 +5344,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal) const Uint32 transId1 = regApiPtr->transid[0]; const Uint32 transId2 = regApiPtr->transid[1]; Uint32 errorCode = 0; - + + regApiPtr->m_exec_flag = 1; switch (regApiPtr->apiConnectstate) { case CS_STARTED: tcConnectptr.i = regApiPtr->firstTcConnect; @@ -6073,11 +6074,17 @@ int Dbtc::releaseAndAbort(Signal* signal) UintR TnoLoops = tcConnectptr.p->noOfNodes; apiConnectptr.p->counter++; + bool prevAlive = false; for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) { localHostptr.i = tcConnectptr.p->tcNodedata[Ti]; ptrCheckGuard(localHostptr, chostFilesize, hostRecord); if (localHostptr.p->hostStatus == HS_ALIVE) { jam(); + if (prevAlive) { + // if previous is alive, its LQH forwards abort to this node + jam(); + continue; + } /* ************< */ /* ABORT < */ /* ************< */ @@ -6087,15 +6094,16 @@ int Dbtc::releaseAndAbort(Signal* signal) signal->theData[2] = apiConnectptr.p->transid[0]; signal->theData[3] = apiConnectptr.p->transid[1]; sendSignal(tblockref, GSN_ABORT, signal, 4, JBB); - return 1; + prevAlive = true; } else { jam(); signal->theData[0] = tcConnectptr.i; signal->theData[1] = apiConnectptr.p->transid[0]; signal->theData[2] = apiConnectptr.p->transid[1]; - signal->theData[3] = hostptr.i; + signal->theData[3] = localHostptr.i; signal->theData[4] = ZFALSE; sendSignal(cownref, GSN_ABORTED, signal, 5, JBB); + prevAlive = false; }//if }//for return 1; diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 7913b4b240e..1ce934a19ca 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -344,6 +344,71 @@ err: return NDBT_FAILED; } +int runLateCommit(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + HugoOperations hugoOps(*ctx->getTab()); + Ndb* pNdb = GETNDB(step); + + int i = 0; + while(iisTestStopped()){ + g_info << i << ": "; + + if(hugoOps.startTransaction(pNdb) != 0) + return NDBT_FAILED; + + if(hugoOps.pkUpdateRecord(pNdb, 1) != 0) + return NDBT_FAILED; + + if(hugoOps.execute_NoCommit(pNdb) != 0) + return NDBT_FAILED; + + Uint32 transNode= hugoOps.getTransaction()->getConnectedNodeId(); + int id = i % restarter.getNumDbNodes(); + int nodeId; + while((nodeId = restarter.getDbNodeId(id)) == transNode) + id = (id + 1) % restarter.getNumDbNodes(); + + ndbout << "Restart node " << nodeId << endl; + + restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true); + + restarter.waitNodesNoStart(&nodeId, 1); + + int res; + if(i & 1) + res= hugoOps.execute_Commit(pNdb); + else + res= hugoOps.execute_Rollback(pNdb); + + ndbout_c("res= %d", res); + + hugoOps.closeTransaction(pNdb); + + restarter.startNodes(&nodeId, 1); + restarter.waitNodesStarted(&nodeId, 1); + + if(i & 1) + { + if(res != 286) + return NDBT_FAILED; + } + else + { + if(res != 0) + return NDBT_FAILED; + } + i++; + } + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", "Test that one node at a time can be stopped and then restarted "\ @@ -600,6 +665,12 @@ TESTCASE("CommittedRead", STEP(runDirtyRead); FINALIZER(runClearTable); } +TESTCASE("LateCommit", + "Test commit after node failure"){ + INITIALIZER(runLoadTable); + STEP(runLateCommit); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt index 5c9b36fb836..ec90a88a77f 100644 --- a/ndb/test/run-test/daily-devel-tests.txt +++ b/ndb/test/run-test/daily-devel-tests.txt @@ -69,6 +69,10 @@ max-time: 2500 cmd: testNodeRestart args: -n CommittedRead T1 +max-time: 2500 +cmd: testNodeRestart +args: -n LateCommit T1 + max-time: 2500 cmd: testNodeRestart args: -n Terror T6 T13 diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 2cfe91da115..632174dc41a 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -272,10 +272,7 @@ foreach my $rdb ( @db_desc ) { my $negated; if ($rdb->{t_regex}) { $t_regex = $rdb->{t_regex}; ## assign temporary regex - $negated = $t_regex =~ tr/~//d; ## remove and count - ## negation operator: we - ## don't allow ~ in table - ## names + $negated = $t_regex =~ s/^~//; ## note and remove negation operator $t_regex = qr/$t_regex/; ## make regex string from ## user regex @@ -820,6 +817,16 @@ sub get_list_of_tables { }); my @dbh_tables = eval { $dbh->tables() }; + + ## Remove quotes around table names + my $quote = $dbh->get_info(29); # SQL_IDENTIFIER_QUOTE_CHAR + if ($quote) { + foreach (@dbh_tables) { + s/^$quote(.*)$quote$/$1/; + s/$quote$quote/$quote/g; + } + } + $dbh->disconnect(); return @dbh_tables; } diff --git a/sql/item.h b/sql/item.h index ca69af39f62..157c48393ba 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1242,6 +1242,8 @@ public: The following class is used to optimize comparing of date and bigint columns We need to save the original item, to be able to set the field to the original value in 'opt_range'. + An instance of Item_int_with_ref may refer to a signed or an unsigned + integer. */ class Item_int_with_ref :public Item_int @@ -1256,6 +1258,11 @@ public: { return ref->save_in_field(field, no_conversions); } + Item *new_item() + { + return (ref->unsigned_flag)? new Item_uint(ref->name, ref->max_length) : + new Item_int(ref->name, ref->max_length); + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dae5f0fc0c6..c0cb0704852 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2289,6 +2289,21 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (check_stack_overrun(thd, buff)) return TRUE; // Fatal error flag is set! + /* + The following optimization reduces the depth of an AND-OR tree. + E.g. a WHERE clause like + F1 AND (F2 AND (F2 AND F4)) + is parsed into a tree with the same nested structure as defined + by braces. This optimization will transform such tree into + AND (F1, F2, F3, F4). + Trees of OR items are flattened as well: + ((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4) + Items for removed AND/OR levels will dangle until the death of the + entire statement. + The optimization is currently prepared statements and stored procedures + friendly as it doesn't allocate any memory and its effects are durable + (i.e. do not depend on PS/SP arguments). + */ while ((item=li++)) { table_map tmp_table_map; @@ -3265,6 +3280,7 @@ Item_equal::Item_equal(Item *c, Item_field *f) const_item= c; } + Item_equal::Item_equal(Item_equal *item_equal) : Item_bool_func(), eval_item(0), cond_false(0) { @@ -3301,12 +3317,7 @@ void Item_equal::add(Item_field *f) uint Item_equal::members() { - uint count= 0; - List_iterator_fast li(fields); - Item_field *item; - while ((item= li++)) - count++; - return count; + return fields.elements; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 212a3dd4501..5a87635a4dc 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1095,6 +1095,12 @@ public: predicates that can not be used to access tables in the investigated plan for those, obtained by substitution of some fields for equal fields, that can be used. + + Prepared Statements/Stored Procedures note: instances of class + Item_equal are created only at the time a PS/SP is executed and + are deleted in the end of execution. All changes made to these + objects need not be registered in the list of changes of the parse + tree and do not harm PS/SP re-execution. */ class Item_equal: public Item_bool_func diff --git a/sql/item_func.cc b/sql/item_func.cc index 88faee95502..37e59fa89d3 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2364,26 +2364,6 @@ longlong Item_func_bit_count::val_int() #ifdef HAVE_DLOPEN -udf_handler::~udf_handler() -{ - if (!not_original) - { - if (initialized) - { - if (u_d->func_deinit != NULL) - { - void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*)) - u_d->func_deinit; - (*deinit)(&initid); - } - free_udf(u_d); - } - if (buffers) // Because of bug in ecc - delete [] buffers; - } -} - - bool udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, uint arg_count, Item **arguments) @@ -2773,6 +2753,31 @@ String *Item_func_udf_str::val_str(String *str) return res; } + +/* + This has to come last in the udf_handler methods, or the compiler for IBM + AIX fails to compile with debugging enabled. (Yes, really.) + */ + +udf_handler::~udf_handler() +{ + if (!not_original) + { + if (initialized) + { + if (u_d->func_deinit != NULL) + { + void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*)) + u_d->func_deinit; + (*deinit)(&initid); + } + free_udf(u_d); + } + if (buffers) // Because of bug in ecc + delete [] buffers; + } +} + #else bool udf_handler::get_arguments() { return 0; } #endif /* HAVE_DLOPEN */ diff --git a/sql/log.cc b/sql/log.cc index 5d77197a9b9..d5c7cd5464f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2457,7 +2457,7 @@ void sql_print_information(const char *format, ...) static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74}; -uint opt_tc_log_size=TC_LOG_MIN_SIZE; +ulong opt_tc_log_size= TC_LOG_MIN_SIZE; ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_page_waits=0, tc_log_cur_pages_used=0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index eb7ab7131dd..97331d3c1a6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -805,6 +805,7 @@ void mysql_stmt_free(THD *thd, char *packet); void mysql_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); void reset_stmt_for_execute(THD *thd, LEX *lex); +void init_stmt_after_parse(THD*, LEX*); /* sql_error.cc */ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce70b05761a..cfd1b87a722 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3147,13 +3147,11 @@ we force server id to 2, but this MySQL server will not act as a slave."); create_shutdown_thread(); create_maintenance_thread(); - printf(ER(ER_READY),my_progname,server_version, - ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port), - mysqld_port); - if (MYSQL_COMPILATION_COMMENT[0] != '\0') - fputs(" " MYSQL_COMPILATION_COMMENT, stdout); - putchar('\n'); - fflush(stdout); + sql_print_information(ER(ER_READY),my_progname,server_version, + ((unix_sock == INVALID_SOCKET) ? (char*) "" + : mysqld_unix_port), + mysqld_port, + MYSQL_COMPILATION_COMMENT); #if defined(__NT__) || defined(HAVE_SMEM) handle_connections_methods(); @@ -4566,7 +4564,7 @@ Disable with --skip-isam.", REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", (gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG, - REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0, 0, TC_LOG_PAGE_SIZE, 0}, + REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0}, {"log-update", OPT_UPDATE_LOG, "The update log is deprecated since version 5.0, is replaced by the binary \ log and this option justs turns on --log-bin instead.", diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index ba4ef70486b..f2772c29b32 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -1824,7 +1824,7 @@ ER_READY cze "%s: p-Bipraven na spojen" dan "%s: klar til tilslutninger" nla "%s: klaar voor verbindingen" - eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d" + eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" jps "%s: ", est "%s: ootab hendusi" fre "%s: Prt pour des connections" @@ -1839,7 +1839,7 @@ ER_READY pol "%s: gotowe do po?czenia" por "%s: Pronto para conexes" rum "%s: sint gata pentru conectii" - rus "%s: .\n: '%s' : '%s' : %d" + rus "%s: .\n: '%s' : '%s' : %d %s" serbian "%s: Spreman za konekcije\n" slo "%s: pripraven na spojenie" spa "%s: preparado para conexiones" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 06669e398ec..ad527d39d21 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -819,6 +819,7 @@ sp_head::restore_lex(THD *thd) LEX *sublex= thd->lex; LEX *oldlex= (LEX *)m_lex.pop(); + init_stmt_after_parse(thd, sublex); if (! oldlex) return; // Nothing to restore diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f5c69269231..87c83771ec8 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1928,7 +1928,8 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length, class GRANT_NAME :public Sql_alloc { public: - char *host,*db, *user, *tname, *hash_key, *orig_host; + acl_host_and_ip host; + char *db, *user, *tname, *hash_key; ulong privs; ulong sort; uint key_length; @@ -1960,12 +1961,10 @@ GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, :privs(p) { /* Host given by user */ - orig_host= strdup_root(&memex,h); - /* Convert empty hostname to '%' for easy comparison */ - host= orig_host[0] ? orig_host : (char*) "%"; + update_hostname(&host, strdup_root(&memex, h)); db = strdup_root(&memex,d); user = strdup_root(&memex,u); - sort= get_sort(3,host,db,user); + sort= get_sort(3,host.hostname,db,user); tname= strdup_root(&memex,t); if (lower_case_table_names) { @@ -1989,17 +1988,12 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, GRANT_NAME::GRANT_NAME(TABLE *form) { - orig_host= host= get_field(&memex, form->field[0]); + update_hostname(&host, get_field(&memex, form->field[0])); db= get_field(&memex,form->field[1]); user= get_field(&memex,form->field[2]); if (!user) user= (char*) ""; - if (!orig_host) - { - orig_host= (char*) ""; - host= (char*) "%"; - } - sort= get_sort(3, orig_host, db, user); + sort= get_sort(3, host.hostname, db, user); tname= get_field(&memex,form->field[3]); if (!db || !tname) { @@ -2042,7 +2036,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) { uint key_prefix_len; KEY_PART_INFO *key_part= col_privs->key_info->key_part; - col_privs->field[0]->store(orig_host,(uint) strlen(orig_host), + col_privs->field[0]->store(host.hostname,(uint) strlen(host.hostname), system_charset_info); col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info); col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info); @@ -2128,17 +2122,12 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, { if (exact) { - if ((host && - !my_strcasecmp(system_charset_info, host, grant_name->host)) || - (ip && !strcmp(ip,grant_name->host))) + if (compare_hostname(&grant_name->host, host, ip)) return grant_name; } else { - if (((host && !wild_case_compare(system_charset_info, - host,grant_name->host)) || - (ip && !wild_case_compare(system_charset_info, - ip,grant_name->host))) && + if (compare_hostname(&grant_name->host, host, ip) && (!found || found->sort < grant_name->sort)) found=grant_name; // Host ok } @@ -3189,7 +3178,7 @@ my_bool grant_init(THD *org_thd) if (check_no_resolve) { - if (hostname_requires_resolving(mem_check->host)) + if (hostname_requires_resolving(mem_check->host.hostname)) { sql_print_warning("'tables_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", @@ -3227,7 +3216,7 @@ my_bool grant_init(THD *org_thd) if (check_no_resolve) { - if (hostname_requires_resolving(mem_check->host)) + if (hostname_requires_resolving(mem_check->host.hostname)) { sql_print_warning("'procs_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", @@ -3541,10 +3530,7 @@ bool check_grant_db(THD *thd,const char *db) idx); if (len < grant_table->key_length && !memcmp(grant_table->hash_key,helping,len) && - (thd->host && !wild_case_compare(system_charset_info, - thd->host,grant_table->host) || - (thd->ip && !wild_case_compare(system_charset_info, - thd->ip,grant_table->host)))) + compare_hostname(&grant_table->host, thd->host, thd->ip)) { error=0; // Found match break; @@ -3964,7 +3950,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, - grant_table->orig_host)) + grant_table->host.hostname)) { ulong table_access= grant_table->privs; if ((table_access | grant_table->cols) != 0) @@ -4071,7 +4057,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, - grant_proc->orig_host)) + grant_proc->host.hostname)) { ulong proc_access= grant_proc->privs; if (proc_access != 0) @@ -4557,19 +4543,22 @@ static int handle_grant_struct(uint struct_no, bool drop, case 1: acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); user= acl_db->user; - host= acl_db->host.hostname; + if (!(host= acl_db->host.hostname)) + host= "%"; break; case 2: grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx); user= grant_name->user; - host= grant_name->host; + if (!(host= grant_name->host.hostname)) + host= "%"; break; case 3: grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx); user= grant_name->user; - host= grant_name->host; + if (!(host= grant_name->host.hostname)) + host= "%"; break; } if (! user) @@ -4624,7 +4613,8 @@ static int handle_grant_struct(uint struct_no, bool drop, case 2: case 3: grant_name->user= strdup_root(&mem, user_to->user.str); - grant_name->host= strdup_root(&mem, user_to->host.str); + update_hostname(&grant_name->host, + strdup_root(&mem, user_to->host.str)); break; } } @@ -5035,7 +5025,7 @@ bool mysql_revoke_all(THD *thd, List &list) counter); if (!(user=grant_table->user)) user= ""; - if (!(host=grant_table->host)) + if (!(host=grant_table->host.hostname)) host= ""; if (!strcmp(lex_user->user.str,user) && @@ -5081,7 +5071,7 @@ bool mysql_revoke_all(THD *thd, List &list) counter); if (!(user=grant_proc->user)) user= ""; - if (!(host=grant_proc->host)) + if (!(host=grant_proc->host.hostname)) host= ""; if (!strcmp(lex_user->user.str,user) && @@ -5153,8 +5143,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name) LEX_USER lex_user; lex_user.user.str= grant_proc->user; lex_user.user.length= strlen(grant_proc->user); - lex_user.host.str= grant_proc->host; - lex_user.host.length= strlen(grant_proc->host); + lex_user.host.str= grant_proc->host.hostname; + lex_user.host.length= strlen(grant_proc->host.hostname); if (!replace_proc_table(thd,grant_proc,tables[4].table,lex_user, grant_proc->db, grant_proc->tname, ~0, 1)) { @@ -5438,7 +5428,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) if (!(table_access & GRANT_ACL)) is_grantable= "NO"; - strxmov(buff,"'",user,"'@'",grant_table->orig_host,"'",NullS); + strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS); if (!test_access) update_schema_privilege(table, buff, grant_table->db, grant_table->tname, 0, 0, "USAGE", 5, is_grantable); @@ -5485,7 +5475,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) is_grantable= "NO"; ulong test_access= table_access & ~GRANT_ACL; - strxmov(buff,"'",user,"'@'",grant_table->orig_host,"'",NullS); + strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS); if (!test_access) continue; else diff --git a/sql/sql_class.h b/sql/sql_class.h index ff30faf1150..e88205568c2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -45,7 +45,7 @@ extern const char **errmesg; #define TC_LOG_PAGE_SIZE 8192 #define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE) -extern uint opt_tc_log_size; +extern ulong opt_tc_log_size; extern ulong tc_log_max_pages_used; extern ulong tc_log_page_size; extern ulong tc_log_page_waits; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 79996ffb65c..738a6e0dbbd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1837,8 +1837,6 @@ void st_select_lex_unit::set_limit(SELECT_LEX *values, select_limit_cnt= values->select_limit+values->offset_limit; if (select_limit_cnt < values->select_limit) select_limit_cnt= HA_POS_ERROR; // no limit - if (select_limit_cnt == HA_POS_ERROR) - sl->options&= ~OPTION_FOUND_ROWS; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 7da5c13e18a..d1594edc3f9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1809,20 +1809,33 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, else { stmt->setup_set_params(); - SELECT_LEX *sl= stmt->lex->all_selects_list; - /* - Save WHERE clause pointers, because they may be changed during query - optimisation. - */ - for (; sl; sl= sl->next_select_in_list()) - sl->prep_where= sl->where; + init_stmt_after_parse(thd, stmt->lex); stmt->state= Item_arena::PREPARED; } DBUG_RETURN(!stmt); } -/* Reinit statement before execution */ +/* + Init PS/SP specific parse tree members. +*/ + +void init_stmt_after_parse(THD *thd, LEX *lex) +{ + SELECT_LEX *sl= lex->all_selects_list; + /* + Save WHERE clause pointers, because they may be changed during query + optimisation. + */ + for (; sl; sl= sl->next_select_in_list()) + sl->prep_where= sl->where; + + for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global) + table->prep_on_expr= table->on_expr; +} + + +/* Reinit prepared statement/stored procedure before execution */ void reset_stmt_for_execute(THD *thd, LEX *lex) { @@ -1883,6 +1896,12 @@ void reset_stmt_for_execute(THD *thd, LEX *lex) tables->table= 0; if (tables->nested_join) tables->nested_join->counter= 0; + + if (tables->prep_on_expr) + { + tables->on_expr= tables->prep_on_expr->copy_andor_structure(thd); + tables->on_expr->cleanup(); + } } lex->current_select= &lex->select_lex; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 67c7d7bbb64..450e0ead65a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6194,9 +6194,9 @@ finish: For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)]) and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]). For b=2 it will be called with *cond_equal=(ptr(CE),[]) - and will transform *cond_equal into (ptr(CE,[Item_equal(2,a,b,c)]). + and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]). For f=e it will be called with *cond_equal=(ptr(CE), []) - and will transform *cond_equal into (ptr(CE,[Item_equal(f,e)]). + and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). NOTES Now only fields that have the same type defintions (verified by @@ -6465,6 +6465,11 @@ static COND *build_equal_items_for_cond(COND *cond, */ while ((item= li++)) { + /* + PS/SP note: we can safely remove a node from AND-OR + structure here because it's restored before each + re-execution of any prepared statement/stored procedure. + */ if (check_equality(item, &cond_equal)) li.remove(); } @@ -6503,6 +6508,11 @@ static COND *build_equal_items_for_cond(COND *cond, if ((new_item = build_equal_items_for_cond(item, inherited))!= item) { /* This replacement happens only for standalone equalities */ + /* + This is ok with PS/SP as the replacement is done for + arguments of an AND/OR item, which are restored for each + execution of PS/SP. + */ li.replace(new_item); } } @@ -6638,10 +6648,12 @@ static COND *build_equal_items(THD *thd, COND *cond, Item *expr; List *join_list= table->nested_join ? &table->nested_join->join_list : NULL; - expr= build_equal_items(thd, table->on_expr, inherited, join_list, - &table->cond_equal); - if (expr != table->on_expr) - thd->change_item_tree(&table->on_expr, expr); + /* + We can modify table->on_expr because its old value will + be restored before re-execution of PS/SP. + */ + table->on_expr= build_equal_items(thd, table->on_expr, inherited, + join_list, &table->cond_equal); } } } @@ -6868,10 +6880,14 @@ static COND* substitute_for_best_equal_field(COND *cond, while ((item= li++)) { Item *new_item =substitute_for_best_equal_field(item, cond_equal, - table_join_idx); + table_join_idx); + /* + This works OK with PS/SP re-execution as changes are made to + the arguments of AND/OR items only + */ if (new_item != item) li.replace(new_item); - } + } if (and_level) { @@ -7200,7 +7216,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) */ expr= simplify_joins(join, &nested_join->join_list, table->on_expr, FALSE); - table->on_expr= expr; + table->prep_on_expr= table->on_expr= expr; } nested_join->used_tables= (table_map) 0; nested_join->not_null_tables=(table_map) 0; @@ -7240,7 +7256,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) } else conds= table->on_expr; - table->on_expr= 0; + table->prep_on_expr= table->on_expr= 0; } } @@ -7321,10 +7337,7 @@ optimize_cond(JOIN *join, COND *conds, List *join_list, DBUG_ENTER("optimize_cond"); if (!conds) - { *cond_value= Item::COND_TRUE; - select->prep_where= 0; - } else { /* diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1339b5e5ed0..7a4ee9f5de3 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1649,6 +1649,10 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) strlen(item_field->field_name), 0))) return 0; } + if (item->type() == Item::SUBSELECT_ITEM && + !item->const_item()) + return 0; + return 1; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 455c83e1718..13c7f0a40b7 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -217,8 +217,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= sl; set_limit(sl, sl); - if (sl->braces) - sl->options&= ~OPTION_FOUND_ROWS; can_skip_order_by= is_union && (!sl->braces || select_limit_cnt == HA_POS_ERROR); @@ -342,10 +340,9 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, if (arena->is_stmt_prepare()) { /* prepare fake select to initialize it correctly */ - ulong options_tmp= init_prepare_fake_select_lex(thd); + (void) init_prepare_fake_select_lex(thd); /* - it should be done only once (because item_list builds only onece - per statement) + Should be done only once (the only item_list per statement). */ DBUG_ASSERT(fake_select_lex->join == 0); if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options, @@ -452,21 +449,14 @@ bool st_select_lex_unit::exec() if (select_limit_cnt < sl->select_limit) select_limit_cnt= HA_POS_ERROR; // no limit - /* - When using braces, SQL_CALC_FOUND_ROWS affects the whole query. - We don't calculate found_rows() per union part - */ - if (select_limit_cnt == HA_POS_ERROR || sl->braces) - sl->options&= ~OPTION_FOUND_ROWS; - else - { - /* - We are doing an union without braces. In this case - SQL_CALC_FOUND_ROWS should be done on all sub parts - */ - sl->options|= found_rows_for_union; - } - sl->join->select_options=sl->options; + /* + When using braces, SQL_CALC_FOUND_ROWS affects the whole query: + we don't calculate found_rows() per union part. + Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts. + */ + sl->join->select_options= + (select_limit_cnt == HA_POS_ERROR || sl->braces) ? + sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union; res= sl->join->optimize(); } if (!res) @@ -498,7 +488,8 @@ bool st_select_lex_unit::exec() } /* Needed for the following test and for records_at_start in next loop */ table->file->info(HA_STATUS_VARIABLE); - if (found_rows_for_union & sl->options) + if (found_rows_for_union && !sl->braces && + select_limit_cnt != HA_POS_ERROR) { /* This is a union without braces. Remember the number of rows that diff --git a/sql/table.h b/sql/table.h index 5ab1f900195..4306d3733c4 100644 --- a/sql/table.h +++ b/sql/table.h @@ -339,6 +339,15 @@ typedef struct st_table_list char *db, *alias, *table_name, *schema_table_name; char *option; /* Used by cache index */ Item *on_expr; /* Used with outer join */ + /* + The scturcture of ON expression presented in the member above + can be changed during certain optimizations. This member + contains a snapshot of AND-OR structure of the ON expression + made after permanent transformations of the parse tree, and is + used to restore ON clause before every reexecution of a prepared + statement or stored procedure. + */ + Item *prep_on_expr; COND_EQUAL *cond_equal; /* Used with outer join */ struct st_table_list *natural_join; /* natural join on this table*/ /* ... join ... USE INDEX ... IGNORE INDEX */ diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 37611a5bd20..8c58520f965 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -416,7 +416,7 @@ static struct wordvalue doubles[] = { #define NEXT_CMP_VALUE(src, p, pass, value, len) \ while (1) { \ if (IS_END(p, src, len)) { \ - if (pass == 0) { p = src; pass++; } \ + if (pass == 0 && len > 0) { p= src; pass++; } \ else { value = 0; break; } \ } \ value = ((pass == 0) ? _sort_order_win1250ch1[*p] \