summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/compile-ia64-debug-max2
-rw-r--r--BitKeeper/etc/logging_ok1
-rwxr-xr-xBuild-tools/Bootstrap10
-rw-r--r--client/mysqldump.c4
-rw-r--r--mysql-test/r/compare.result3
-rw-r--r--mysql-test/r/derived.result9
-rw-r--r--mysql-test/r/mysqldump.result36
-rw-r--r--mysql-test/r/rpl_multi_update2.result42
-rw-r--r--mysql-test/r/subselect.result48
-rw-r--r--mysql-test/t/compare.test3
-rw-r--r--mysql-test/t/derived.test10
-rw-r--r--mysql-test/t/rpl_multi_update2-slave.opt1
-rw-r--r--mysql-test/t/rpl_multi_update2.test33
-rw-r--r--mysql-test/t/subselect.test56
-rw-r--r--sql/examples/ha_archive.cc27
-rw-r--r--sql/ha_innodb.cc18
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_cmpfunc.h9
-rw-r--r--sql/item_func.cc18
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_subselect.cc16
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/sql_base.cc14
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc81
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_update.cc55
-rw-r--r--strings/ctype-simple.c2
32 files changed, 458 insertions, 76 deletions
diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max
index 9cd54de428d..56c36059ea9 100755
--- a/BUILD/compile-ia64-debug-max
+++ b/BUILD/compile-ia64-debug-max
@@ -9,5 +9,5 @@ then
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
fi
-CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server
+CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server --with-archive-storage-engine
gmake
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 483f324d89c..6ccc886e161 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -33,6 +33,7 @@ bk@mysql.r18.ru
brian@avenger.(none)
brian@brian-akers-computer.local
brian@private-client-ip-101.oz.net
+brian@zim.(none)
carsten@tsort.bitbybit.dk
davida@isil.mysql.com
dellis@goetia.(none)
diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap
index 10ebc5c2dd1..827eb4022d7 100755
--- a/Build-tools/Bootstrap
+++ b/Build-tools/Bootstrap
@@ -210,10 +210,16 @@ if (-d $target_dir)
}
else
{
- &logger("Renaming $target_dir to $target_dir.old." . $$);
+ # Get the time stamp of "configure.in"
+ @stat= stat("$target_dir/configure.in");
+ my $mtime= $stat[9];
+ my ($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
+ my $mtime= sprintf("%04d%-02d-%02d-%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min);
+
+ &logger("Renaming $target_dir to $target_dir-$mtime");
$command= "mv ";
$command.= "-v " if ($opt_verbose || defined $opt_log);
- $command.= "$target_dir $target_dir.old." . $$;
+ $command.= "$target_dir $target_dir-$mtime";
&run_command($command, "Could not rename $target_dir!");
}
}
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 3a93adf5b36..afaa2dc5a6d 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -489,7 +489,7 @@ static void write_header(FILE *sql_file, char *db_name)
");
}
fprintf(sql_file,
- "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\"%s%s%s\" */;\n",
+ "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='%s%s%s' */;\n",
path?"":"NO_AUTO_VALUE_ON_ZERO",compatible_mode_normal_str[0]==0?"":",",
compatible_mode_normal_str);
check_io(sql_file);
@@ -863,7 +863,7 @@ static int dbConnect(char *host, char *user,char *passwd)
cannot reconnect.
*/
sock->reconnect= 0;
- sprintf(buff, "/*!40100 SET @@SQL_MODE=\"%s\" */",
+ sprintf(buff, "/*!40100 SET @@SQL_MODE='%s' */",
compatible_mode_normal_str);
if (mysql_query_with_error_report(sock, 0, buff))
{
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index bf8a5106044..49ec2dd85cc 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -36,3 +36,6 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ')
6109 -1 -1
61 0 0
DROP TABLE t1;
+SELECT CHAR(31) = '', '' = CHAR(31);
+CHAR(31) = '' '' = CHAR(31)
+0 0
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 7e6b9b44566..61d745d0236 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -330,3 +330,12 @@ SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MA
min max avg
10.00 10.00 10
DROP TABLE t1;
+create table t1 (a integer, b integer);
+insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1);
+select distinct sum(b) from t1 group by a;
+sum(b)
+4
+select distinct sum(b) from (select a,b from t1) y group by a;
+sum(b)
+4
+drop table t1;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 623bd2a0f3c..8f2294caa48 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -60,7 +60,7 @@ INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456)
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` decimal(10,5) default NULL,
@@ -83,7 +83,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
CREATE TABLE `t1` (
`a` decimal(10,5) default NULL,
`b` float default NULL
@@ -149,7 +149,7 @@ INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL);
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` varchar(255) default NULL
@@ -175,7 +175,7 @@ CREATE TABLE t1 (a int) ENGINE=MYISAM;
INSERT INTO t1 VALUES (1), (2);
/*!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,MYSQL40" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL40' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -194,7 +194,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -225,7 +225,7 @@ create table t1(a int);
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -246,7 +246,7 @@ UNLOCK TABLES;
/*!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,ANSI" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */;
DROP TABLE IF EXISTS "t1";
CREATE TABLE "t1" (
"a" int(11) default NULL
@@ -270,7 +270,7 @@ set global sql_mode='ANSI_QUOTES';
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -291,7 +291,7 @@ UNLOCK TABLES;
/*!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,ANSI" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */;
DROP TABLE IF EXISTS "t1";
CREATE TABLE "t1" (
"a" int(11) default NULL
@@ -316,7 +316,7 @@ insert into t1 values (1),(2),(3);
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
@@ -339,7 +339,7 @@ drop table t1;
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
@@ -360,7 +360,7 @@ create database mysqldump_test_db character set latin2 collate latin2_bin;
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CHARACTER SET latin2 COLLATE latin2_bin */;
@@ -383,7 +383,7 @@ INSERT INTO t1 VALUES (_latin1 'ÄÖÜß');
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` char(10) default NULL
@@ -405,7 +405,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` char(10) default NULL
@@ -424,7 +424,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` char(10) default NULL
@@ -443,7 +443,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` char(10) default NULL
@@ -462,7 +462,7 @@ UNLOCK TABLES;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` char(10) default NULL
@@ -491,7 +491,7 @@ INSERT INTO t2 VALUES (4),(5),(6);
/*!40101 SET NAMES utf8 */;
/*!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" */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`a` int(11) default NULL
diff --git a/mysql-test/r/rpl_multi_update2.result b/mysql-test/r/rpl_multi_update2.result
new file mode 100644
index 00000000000..99356ebf970
--- /dev/null
+++ b/mysql-test/r/rpl_multi_update2.result
@@ -0,0 +1,42 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 4
+2 5
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+SELECT * FROM t1 ORDER BY a;
+a b
+1 4
+2 5
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 02662f9900a..437fd624ae1 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2160,3 +2160,51 @@ ERROR 42S22: Unknown column 'a2' in 'scalar IN/ALL/ANY subquery'
select * from t1 where a1 > any(select b1 from t2);
a1
drop table t1,t2;
+create table t1 (a integer, b integer);
+select (select * from t1) = (select 1,2);
+(select * from t1) = (select 1,2)
+NULL
+select (select 1,2) = (select * from t1);
+(select 1,2) = (select * from t1)
+NULL
+select row(1,2) = ANY (select * from t1);
+row(1,2) = ANY (select * from t1)
+0
+select row(1,2) != ALL (select * from t1);
+row(1,2) != ALL (select * from t1)
+1
+drop table t1;
+create table t1 (a integer, b integer);
+select row(1,(2,2)) in (select * from t1 );
+ERROR 21000: Operand should contain 2 column(s)
+select row(1,(2,2)) = (select * from t1 );
+ERROR 21000: Operand should contain 2 column(s)
+select (select * from t1) = row(1,(2,2));
+ERROR 21000: Operand should contain 1 column(s)
+drop table t1;
+create table t1 (a integer);
+insert into t1 values (1);
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ;
+ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
+ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
+select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx );
+xx 1 = ALL ( select 1 from t1 where 1 = xx )
+1 1
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
+ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
+ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
+drop table t1;
+CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1,1,1);
+INSERT INTO t2 VALUES (1,1,1);
+PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
+count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
+EXECUTE my_stmt;
+b count(*)
+EXECUTE my_stmt;
+b count(*)
+deallocate prepare my_stmt;
+drop table t1,t2;
diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test
index b0cef48dd3f..e3c042e608a 100644
--- a/mysql-test/t/compare.test
+++ b/mysql-test/t/compare.test
@@ -30,3 +30,6 @@ CREATE TABLE t1 (a char(10) not null);
INSERT INTO t1 VALUES ('a'),('a\0'),('a\t'),('a ');
SELECT hex(a),STRCMP(a,'a'), STRCMP(a,'a ') FROM t1;
DROP TABLE t1;
+
+# Bug #8134: Comparison against CHAR(31) at end of string
+SELECT CHAR(31) = '', '' = CHAR(31);
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 64e3fe8929b..8b322746ed6 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -214,3 +214,13 @@ CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) N
insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);
SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MAX(concat(date_,";",price)), 12) price FROM t1 WHERE itemid=128 AND grpid='rozn' GROUP BY itemid, grpid, vendor) lastprices;
DROP TABLE t1;
+
+#
+# DISTINCT over grouped select on subquery in the FROM clause
+#
+create table t1 (a integer, b integer);
+insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1);
+select distinct sum(b) from t1 group by a;
+select distinct sum(b) from (select a,b from t1) y group by a;
+drop table t1;
+
diff --git a/mysql-test/t/rpl_multi_update2-slave.opt b/mysql-test/t/rpl_multi_update2-slave.opt
new file mode 100644
index 00000000000..17d4171af0e
--- /dev/null
+++ b/mysql-test/t/rpl_multi_update2-slave.opt
@@ -0,0 +1 @@
+--replicate-ignore-table=nothing.sensible
diff --git a/mysql-test/t/rpl_multi_update2.test b/mysql-test/t/rpl_multi_update2.test
new file mode 100644
index 00000000000..bba7700a88e
--- /dev/null
+++ b/mysql-test/t/rpl_multi_update2.test
@@ -0,0 +1,33 @@
+# Let's verify that multi-update is not always skipped by slave if
+# some replicate-* rules exist.
+# (BUG#7011)
+
+source include/master-slave.inc;
+
+CREATE TABLE t1 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned
+) ENGINE=MyISAM;
+
+CREATE TABLE t2 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 3ee498ee380..cdec080611d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1414,8 +1414,11 @@ SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
drop table t1,t2;
+
+#
# Test for BUG#7885: Server crash when 'any' subselect compared to
# non-existant field.
+#
create table t1 (a1 int);
create table t2 (b1 int);
--error 1054
@@ -1423,3 +1426,56 @@ select * from t1 where a2 > any(select b1 from t2);
select * from t1 where a1 > any(select b1 from t2);
drop table t1,t2;
+
+#
+# Comparison subquery with * and row
+#
+create table t1 (a integer, b integer);
+select (select * from t1) = (select 1,2);
+select (select 1,2) = (select * from t1);
+# queries whih can be converted to IN
+select row(1,2) = ANY (select * from t1);
+select row(1,2) != ALL (select * from t1);
+drop table t1;
+
+#
+# Comparison subquery and row with nested rows
+#
+create table t1 (a integer, b integer);
+-- error 1241
+select row(1,(2,2)) in (select * from t1 );
+-- error 1241
+select row(1,(2,2)) = (select * from t1 );
+-- error 1241
+select (select * from t1) = row(1,(2,2));
+drop table t1;
+
+#
+# Forward reference detection
+#
+create table t1 (a integer);
+insert into t1 values (1);
+-- error 1247
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ;
+-- error 1247
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
+select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx );
+-- error 1247
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
+-- error 1247
+select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
+drop table t1;
+
+#
+# cleaning up of results of subselects (BUG#8125)
+#
+CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1,1,1);
+INSERT INTO t2 VALUES (1,1,1);
+PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
+count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
+EXECUTE my_stmt;
+EXECUTE my_stmt;
+deallocate prepare my_stmt;
+drop table t1,t2;
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index e8d07a99048..491056d0e59 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -42,18 +42,20 @@
handle bulk inserts as well (that is if someone was trying to read at
the same time since we would want to flush).
- A "meta" file is kept. All this file does is contain information on
- the number of rows.
+ A "meta" file is kept alongside the data file. This file serves two purpose.
+ The first purpose is to track the number of rows in the table. The second
+ purpose is to determine if the table was closed properly or not. When the
+ meta file is first opened it is marked as dirty. It is opened when the table
+ itself is opened for writing. When the table is closed the new count for rows
+ is written to the meta file and the file is marked as clean. If the meta file
+ is opened and it is marked as dirty, it is assumed that a crash occured. At
+ this point an error occurs and the user is told to rebuild the file.
+ A rebuild scans the rows and rewrites the meta file. If corruption is found
+ in the data file then the meta file is not repaired.
- No attempts at durability are made. You can corrupt your data. A repair
- method was added to repair the meta file that stores row information,
- but if your data file gets corrupted I haven't solved that. I could
- create a repair that would solve this, but do you want to take a
- chance of loosing your data?
+ At some point a recovery method for such a drastic case needs to be divised.
- Locks are row level, and you will get a consistant read. Transactions
- will be added later (they are not that hard to add at this
- stage).
+ Locks are row level, and you will get a consistant read.
For performance as far as table scans go it is quite fast. I don't have
good numbers but locally it has out performed both Innodb and MyISAM. For
@@ -88,7 +90,6 @@
compression but may speed up ordered searches).
Checkpoint the meta file to allow for faster rebuilds.
Dirty open (right now the meta file is repaired if a crash occured).
- Transactions.
Option to allow for dirty reads, this would lower the sync calls, which would make
inserts a lot faster, but would mean highly arbitrary reads.
@@ -355,6 +356,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
opposite.
*/
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
+
/*
It is expensive to open and close the data files and since you can't have
a gzip file that can be both read and written we keep a writer open
@@ -401,7 +403,8 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
if (gzclose(share->archive_write) == Z_ERRNO)
rc= 1;
- my_close(share->meta_file,MYF(0));
+ if (my_close(share->meta_file, MYF(0)))
+ rc= 1;
my_free((gptr) share, MYF(0));
}
pthread_mutex_unlock(&archive_mutex);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 502f8eb92f3..1d75ce99aee 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4672,12 +4672,12 @@ ha_innobase::update_table_comment(
dict_print_info_on_foreign_keys(FALSE, file,
prebuilt->trx, prebuilt->table);
flen = ftell(file);
- if(length + flen + 3 > 64000) {
+ if (flen < 0) {
+ flen = 0;
+ } else if (length + flen + 3 > 64000) {
flen = 64000 - 3 - length;
}
- ut_ad(flen > 0);
-
/* allocate buffer for the full string, and
read the contents of the temporary file */
@@ -4741,12 +4741,12 @@ ha_innobase::get_foreign_key_create_info(void)
prebuilt->trx->op_info = (char*)"";
flen = ftell(file);
- if(flen > 64000 - 1) {
+ if (flen < 0) {
+ flen = 0;
+ } else if(flen > 64000 - 1) {
flen = 64000 - 1;
}
- ut_ad(flen >= 0);
-
/* allocate buffer for the string, and
read the contents of the temporary file */
@@ -5142,12 +5142,12 @@ innodb_show_status(
srv_printf_innodb_monitor(srv_monitor_file);
flen = ftell(srv_monitor_file);
os_file_set_eof(srv_monitor_file);
- if(flen > 64000 - 1) {
+ if (flen < 0) {
+ flen = 0;
+ } else if (flen > 64000 - 1) {
flen = 64000 - 1;
}
- ut_ad(flen > 0);
-
/* allocate buffer for the string, and
read the contents of the temporary file */
diff --git a/sql/item.cc b/sql/item.cc
index 8c45dffce75..ab29c147dfb 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1482,12 +1482,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
else if (refer != (Item **)not_found_item)
{
- if (!(*refer)->fixed)
+ if (!last->ref_pointer_array[counter])
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
+ DBUG_ASSERT((*refer)->fixed);
/*
Here, a subset of actions performed by Item_ref::set_properties
is not enough. So we pass ptr to NULL into Item_[direct]_ref
@@ -2161,12 +2162,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
mark_as_dependent(thd, last, thd->lex->current_select, fld);
return 0;
}
- if (!(*ref)->fixed)
+ if (!last->ref_pointer_array[counter])
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
+ DBUG_ASSERT((*ref)->fixed);
mark_as_dependent(thd, last, thd->lex->current_select,
this);
if (place == IN_HAVING)
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 6834799688d..061ed468b78 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -213,7 +213,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2
public:
Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
{
- allowed_arg_cols= a->cols();
+ allowed_arg_cols= 0; // Fetch this value from first argument
}
Item *neg_transformer(THD *thd);
virtual Item *negated_item();
@@ -390,7 +390,10 @@ class Item_func_interval :public Item_int_func
double *intervals;
public:
Item_func_interval(Item_row *a)
- :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
+ :Item_int_func(a),row(a),intervals(0)
+ {
+ allowed_arg_cols= 0; // Fetch this value from first argument
+ }
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
@@ -743,7 +746,7 @@ class Item_func_in :public Item_int_func
Item_func_in(List<Item> &list)
:Item_int_func(list), array(0), in_item(0), have_null(0)
{
- allowed_arg_cols= args[0]->cols();
+ allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int();
void fix_length_and_dec();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7125f4704b8..bff49541252 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -303,10 +303,24 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
We can't yet set item to *arg as fix_fields may change *arg
We shouldn't call fix_fields() twice, so check 'fixed' field first
*/
- if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
- (*arg)->check_cols(allowed_arg_cols))
+ if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
return 1; /* purecov: inspected */
+
item= *arg;
+
+ if (allowed_arg_cols)
+ {
+ if (item->check_cols(allowed_arg_cols))
+ return 1;
+ }
+ else
+ {
+ /* we have to fetch allowed_arg_cols from first argument */
+ DBUG_ASSERT(arg == args); // it is first argument
+ allowed_arg_cols= item->cols();
+ DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
+ }
+
if (item->maybe_null)
maybe_null=1;
diff --git a/sql/item_func.h b/sql/item_func.h
index ce2b34499d6..8a5347d675e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -32,6 +32,10 @@ class Item_func :public Item_result_field
{
protected:
Item **args, *tmp_arg[2];
+ /*
+ Allowed numbers of columns in result (usually 1, which means scalar value)
+ 0 means get this number from first argument
+ */
uint allowed_arg_cols;
public:
uint arg_count;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 8516ea76a7e..16186b1a6d3 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -995,6 +995,10 @@ Item_in_subselect::row_value_transformer(JOIN *join)
List_iterator_fast<Item> li(select_lex->item_list);
for (uint i= 0; i < n; i++)
{
+ DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed);
+ if (select_lex->ref_pointer_array[i]->
+ check_cols(left_expr->el(i)->cols()))
+ goto err;
Item *func= new Item_ref_null_helper(this,
select_lex->ref_pointer_array+i,
(char *) "<no matter>",
@@ -1123,6 +1127,7 @@ void subselect_single_select_engine::cleanup()
DBUG_ENTER("subselect_single_select_engine::cleanup");
prepared= optimized= executed= 0;
join= 0;
+ result->cleanup();
DBUG_VOID_RETURN;
}
@@ -1131,6 +1136,7 @@ void subselect_union_engine::cleanup()
{
DBUG_ENTER("subselect_union_engine::cleanup");
unit->reinit_exec_mechanism();
+ result->cleanup();
DBUG_VOID_RETURN;
}
@@ -1138,6 +1144,10 @@ void subselect_union_engine::cleanup()
void subselect_uniquesubquery_engine::cleanup()
{
DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
+ /*
+ subselect_uniquesubquery_engine have not 'result' assigbed, so we do not
+ cleanup() it
+ */
DBUG_VOID_RETURN;
}
@@ -1421,13 +1431,15 @@ int subselect_indexsubquery_engine::exec()
uint subselect_single_select_engine::cols()
{
- return select_lex->item_list.elements;
+ DBUG_ASSERT(select_lex->join); // should be called after fix_fields()
+ return select_lex->join->fields_list.elements;
}
uint subselect_union_engine::cols()
{
- return unit->first_select()->item_list.elements;
+ DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields()
+ return unit->types.elements;
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e71833e6af6..6218bc49f53 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -377,6 +377,7 @@ Item *negate_expression(THD *thd, Item *expr);
struct Query_cache_query_flags
{
unsigned int client_long_flag:1;
+ unsigned int client_protocol_41:1;
uint character_set_client_num;
uint character_set_results_num;
uint collation_connection_num;
@@ -564,6 +565,10 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
COND *conds, ulong options,
enum enum_duplicates handle_duplicates, bool ignore,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
+int mysql_multi_update_lock(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> *fields,
+ SELECT_LEX *select_lex);
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *insert_table_list, TABLE *table,
List<Item> &fields, List_item *values,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7d26996856d..7434897ab90 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2405,6 +2405,20 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
+ /*
+ To prevent fail on forward lookup we fill it with zerows,
+ then if we got pointer on zero after find_item_in_list we will know
+ that it is forward lookup.
+
+ There is other way to solve problem: fill array with pointers to list,
+ but it will be slower.
+
+ TODO: remove it when (if) we made one list for allfields and
+ ref_pointer_array
+ */
+ if (ref_pointer_array)
+ bzero(ref_pointer_array, sizeof(Item *) * fields.elements);
+
Item **ref= ref_pointer_array;
while ((item= it++))
{
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 55e96ec0c6d..e1367412601 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -776,6 +776,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
1 : 0);
+ flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
+ 1 : 0);
flags.character_set_client_num=
thd->variables.character_set_client->number;
flags.character_set_results_num=
@@ -968,6 +970,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
1 : 0);
+ flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
+ 1 : 0);
flags.character_set_client_num= thd->variables.character_set_client->number;
flags.character_set_results_num=
(thd->variables.character_set_results ?
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 596097d9dc2..e11d8369f57 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1240,6 +1240,14 @@ bool select_singlerow_subselect::send_data(List<Item> &items)
}
+void select_max_min_finder_subselect::cleanup()
+{
+ DBUG_ENTER("select_max_min_finder_subselect::cleanup");
+ cache= 0;
+ DBUG_VOID_RETURN;
+}
+
+
bool select_max_min_finder_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_max_min_finder_subselect::send_data");
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ce60ed06cfd..55099791ae0 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1381,6 +1381,7 @@ public:
select_max_min_finder_subselect(Item_subselect *item, bool mx)
:select_subselect(item), cache(0), fmax(mx)
{}
+ void cleanup();
bool send_data(List<Item> &items);
bool cmp_real();
bool cmp_int();
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3ac783da9c4..ed974a48ad3 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -164,7 +164,10 @@ void lex_start(THD *thd, uchar *buf,uint length)
void lex_end(LEX *lex)
{
- lex->select_lex.expr_list.delete_elements(); // If error when parsing sql-varargs
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ sl->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e2e0bc61c23..7cb71607edf 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -371,6 +371,7 @@ public:
ulong init_prepare_fake_select_lex(THD *thd);
int change_result(select_subselect *result, select_subselect *old_result);
+ inline bool is_prepared() { return prepared; }
friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d3a5617d01e..85cd24c4fbb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -52,6 +52,8 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
#endif
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
+static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
+ List<Item> *fields, SELECT_LEX *select_lex);
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
@@ -1883,6 +1885,8 @@ mysql_execute_command(THD *thd)
{
int res= 0;
LEX *lex= thd->lex;
+ bool slave_fake_lock= 0;
+ MYSQL_LOCK *fake_prev_lock= 0;
SELECT_LEX *select_lex= &lex->select_lex;
TABLE_LIST *tables= (TABLE_LIST*) select_lex->table_list.first;
SELECT_LEX_UNIT *unit= &lex->unit;
@@ -1900,6 +1904,23 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
{
+ if (lex->sql_command == SQLCOM_UPDATE_MULTI)
+ {
+ DBUG_PRINT("info",("need faked locked tables"));
+
+ if (check_multi_update_lock(thd, tables, &select_lex->item_list,
+ select_lex))
+ goto error;
+
+ /* Fix for replication, the tables are opened and locked,
+ now we pretend that we have performed a LOCK TABLES action */
+
+ fake_prev_lock= thd->locked_tables;
+ if (thd->lock)
+ thd->locked_tables= thd->lock;
+ thd->lock= 0;
+ slave_fake_lock= 1;
+ }
/*
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated
@@ -3582,6 +3603,14 @@ purposes internal to the MySQL server", MYF(0));
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
error:
+ if (unlikely(slave_fake_lock))
+ {
+ DBUG_PRINT("info",("undoing faked lock"));
+ thd->lock= thd->locked_tables;
+ thd->locked_tables= fake_prev_lock;
+ if (thd->lock == thd->locked_tables)
+ thd->lock= 0;
+ }
DBUG_VOID_RETURN;
}
@@ -5012,6 +5041,58 @@ bool check_simple_select()
return 0;
}
+/*
+ Setup locking for multi-table updates. Used by the replication slave.
+ Replication slave SQL thread examines (all_tables_not_ok()) the
+ locking state of referenced tables to determine if the query has to
+ be executed or ignored. Since in multi-table update, the
+ 'default' lock is read-only, this lock is corrected early enough by
+ calling this function, before the slave decides to execute/ignore.
+
+ SYNOPSIS
+ check_multi_update_lock()
+ thd Current thread
+ tables List of user-supplied tables
+ fields List of fields requiring update
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
+ List<Item> *fields, SELECT_LEX *select_lex)
+{
+ bool res= 1;
+ TABLE_LIST *table;
+ DBUG_ENTER("check_multi_update_lock");
+
+ if (check_db_used(thd, tables))
+ goto error;
+
+ /*
+ Ensure that we have UPDATE or SELECT privilege for each table
+ The exact privilege is checked in mysql_multi_update()
+ */
+ for (table= tables ; table ; table= table->next)
+ {
+ TABLE_LIST *save= table->next;
+ table->next= 0;
+ if ((check_access(thd, UPDATE_ACL, table->db, &table->grant.privilege,0,1) ||
+ (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) &&
+ check_one_table_access(thd, SELECT_ACL, table))
+ goto error;
+ table->next= save;
+ }
+
+ if (mysql_multi_update_lock(thd, tables, fields, select_lex))
+ goto error;
+
+ res= 0;
+
+error:
+ DBUG_RETURN(res);
+}
+
Comp_creator *comp_eq_creator(bool invert)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ccfcb213068..8353ca9333d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1320,7 +1320,7 @@ JOIN::exec()
curr_join->select_distinct=0; /* Each row is unique */
curr_join->join_free(0); /* Free quick selects */
- if (select_distinct && ! group_list)
+ if (curr_join->select_distinct && ! curr_join->group_list)
{
thd->proc_info="Removing duplicates";
if (curr_join->tmp_having)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c2894a0c86b..6ca794283f1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -464,30 +464,23 @@ static table_map get_table_map(List<Item> *items)
}
-
/*
- Setup multi-update handling and call SELECT to do the join
+ Prepare tables for multi-update
+ Analyse which tables need specific privileges and perform locking
+ as required
*/
-int mysql_multi_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> *fields,
- List<Item> *values,
- COND *conds,
- ulong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
+int mysql_multi_update_lock(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> *fields,
+ SELECT_LEX *select_lex)
{
int res;
- multi_update *result;
TABLE_LIST *tl;
TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first;
- List<Item> total_list;
const bool using_lock_tables= thd->locked_tables != 0;
bool initialized_dervied= 0;
- DBUG_ENTER("mysql_multi_update");
-
- select_lex->select_limit= HA_POS_ERROR;
+ DBUG_ENTER("mysql_multi_update_lock");
/*
The following loop is here to to ensure that we only lock tables
@@ -593,7 +586,7 @@ int mysql_multi_update(THD *thd,
(grant_option && check_grant(thd, wants, tl, 0, 0, 0)))
{
tl->next= save;
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
tl->next= save;
}
@@ -616,11 +609,7 @@ int mysql_multi_update(THD *thd,
/* Relock the tables with the correct modes */
res= lock_tables(thd, table_list, table_count);
if (using_lock_tables)
- {
- if (res)
- DBUG_RETURN(res);
break; // Don't have to do setup_field()
- }
/*
We must setup fields again as the file may have been reopened
@@ -651,6 +640,32 @@ int mysql_multi_update(THD *thd,
*/
close_thread_tables(thd);
}
+
+ DBUG_RETURN(res);
+}
+
+/*
+ Setup multi-update handling and call SELECT to do the join
+*/
+
+int mysql_multi_update(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> *fields,
+ List<Item> *values,
+ COND *conds,
+ ulong options,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
+{
+ int res;
+ TABLE_LIST *tl;
+ TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first;
+ List<Item> total_list;
+ multi_update *result;
+ DBUG_ENTER("mysql_multi_update");
+
+ if ((res= mysql_multi_update_lock(thd, table_list, fields, select_lex)))
+ DBUG_RETURN(res);
/* Setup timestamp handling */
for (tl= update_list; tl; tl= tl->next)
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 5bfa9e52595..4dc6a1be27b 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -153,7 +153,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
/* put shorter key in s */
a_length= b_length;
a= b;
- swap= -1; /* swap sign of result */
+ swap= -1^1; /* swap sign of result */
}
for (end= a + a_length-length; a < end ; a++)
{