List:Commits« Previous MessageNext Message »
From:MySQL Release Engineering Date:July 5 2011 10:59pm
Subject:bzr push into mysql-5.1 branch (mysql-re_ww:3564 to 3565)
View as plain text  
 3565 Karen Langford	2011-07-06 [merge]
      Merge from mysql-5.1.58-release

    removed:
      storage/ndb/test/sql/
      storage/ndb/test/sql/BANK.sql
      storage/ndb/test/sql/T1.sql
      storage/ndb/test/sql/test_create_drop.pl
      storage/ndb/test/sql/test_range_bounds.pl
    added:
      mysql-test/r/secure_file_priv_win.result
      mysql-test/t/secure_file_priv_win-master.opt
      mysql-test/t/secure_file_priv_win.test
    modified:
      mysql-test/r/explain.result
      mysql-test/r/sp-security.result
      mysql-test/r/subselect.result
      mysql-test/suite/innodb_plugin/r/innodb-index.result
      mysql-test/suite/innodb_plugin/t/innodb-index.test
      mysql-test/t/explain.test
      mysql-test/t/sp-security.test
      mysql-test/t/subselect.test
      mysys/my_symlink.c
      sql/item.cc
      sql/item_subselect.cc
      sql/item_sum.cc
      sql/mysql_priv.h
      sql/mysqld.cc
      sql/sp_head.cc
      sql/sql_connect.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_load.cc
      sql/sql_partition.cc
      sql/sql_select.cc
      storage/innodb_plugin/ChangeLog
      storage/innodb_plugin/row/row0row.c
 3564 Jon Olav Hauglid	2011-07-04
      Fix MTR broken by last push.

    modified:
      mysql-test/include/mtr_check.sql
      mysql-test/include/mtr_warnings.sql
=== modified file 'mysql-test/r/explain.result'
--- a/mysql-test/r/explain.result	2010-10-18 12:12:27 +0000
+++ b/mysql-test/r/explain.result	2011-05-04 15:12:45 +0000
@@ -176,11 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_
 SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
 EXPLAIN EXTENDED SELECT 1 FROM t1
 WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
-ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
-SHOW WARNINGS;
-Level	Code	Message
-Error	1140	Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
-Note	1003	select 1 AS `1` from `test`.`t1` where <not>(<exists>(...))
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+2	SUBQUERY	t1	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
+2	SUBQUERY	t	system	NULL	NULL	NULL	NULL	0	0.00	const row not found
+Warnings:
+Note	1003	select 1 AS `1` from `test`.`t1` where 0
 SET SESSION sql_mode=@old_sql_mode;
 DROP TABLE t1;
 End of 5.0 tests.

=== added file 'mysql-test/r/secure_file_priv_win.result'
--- a/mysql-test/r/secure_file_priv_win.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/secure_file_priv_win.result	2011-05-04 12:47:29 +0000
@@ -0,0 +1,38 @@
+CREATE TABLE t1 (c1 longtext);
+INSERT INTO t1 values ('a');
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517.tmp';
+show global variables like 'secure_file_priv';
+Variable_name	Value
+secure_file_priv	MYSQL_TMP_DIR/
+SELECT load_file('MYSQL_TMP_DIR\\B11764517.tmp') AS x;
+x
+a
+
+SELECT load_file('MYSQL_TMP_DIR/B11764517.tmp') AS x;
+x
+a
+
+SELECT load_file('MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
+x
+a
+
+SELECT load_file('MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
+x
+a
+
+SELECT load_file('MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp') AS x;
+x
+NULL
+LOAD DATA INFILE 'MYSQL_TMP_DIR\\B11764517.tmp' INTO TABLE t1;
+LOAD DATA INFILE 'MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
+LOAD DATA INFILE 'MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
+LOAD DATA INFILE 'MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
+LOAD DATA INFILE "MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp" into table t1;
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517-2.tmp';
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\B11764517-2.tmp';
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517-3.tmp';
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
+SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
+DROP TABLE t1;

=== modified file 'mysql-test/r/sp-security.result'
--- a/mysql-test/r/sp-security.result	2010-02-26 13:16:46 +0000
+++ b/mysql-test/r/sp-security.result	2011-04-13 07:57:16 +0000
@@ -567,3 +567,28 @@ DROP USER 'tester';
 DROP USER 'Tester';
 DROP DATABASE B48872;
 End of 5.0 tests.
+#
+# Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
+#              DEFINITION OF ANY ROUTINE. 
+#
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1;
+CREATE PROCEDURE db1.p1() SELECT 1;
+CREATE USER user2@localhost IDENTIFIED BY '';
+GRANT SELECT(db) ON mysql.proc TO user2@localhost;
+# Connection con2 as user2
+# The statement below before disclosed info from body_utf8 column.
+SHOW CREATE PROCEDURE db1.p1;
+ERROR 42000: PROCEDURE p1 does not exist
+# Check that SHOW works with SELECT grant on whole table
+# Connection default
+GRANT SELECT ON mysql.proc TO user2@localhost;
+# Connection con2
+# This should work
+SHOW CREATE PROCEDURE db1.p1;
+Procedure	sql_mode	Create Procedure	character_set_client	collation_connection	Database Collation
+p1		CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+SELECT 1	latin1	latin1_swedish_ci	latin1_swedish_ci
+# Connection default
+DROP USER user2@localhost;
+DROP DATABASE db1;

=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result	2011-04-14 14:35:24 +0000
+++ b/mysql-test/r/subselect.result	2011-05-10 13:57:40 +0000
@@ -4435,6 +4435,32 @@ pk	int_key
 3	3
 7	3
 DROP TABLE t1,t2;
+#
+# Bug#12329653 
+# EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
+#
+CREATE TABLE t1(a1 int);
+INSERT INTO t1 VALUES (1),(2);
+SELECT @@session.sql_mode INTO @old_sql_mode;
+SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
+SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
+1
+1
+1
+PREPARE stmt FROM 
+'SELECT 1 UNION ALL 
+SELECT 1 FROM t1
+ORDER BY
+(SELECT 1 FROM t1 AS t1_0  
+  WHERE 1 < SOME (SELECT a1 FROM t1)
+)' ;
+EXECUTE stmt ;
+ERROR 21000: Subquery returns more than 1 row
+EXECUTE stmt ;
+ERROR 21000: Subquery returns more than 1 row
+SET SESSION sql_mode=@old_sql_mode;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
 End of 5.0 tests.
 CREATE TABLE t1 (a INT, b INT);
 INSERT INTO t1 VALUES (2,22),(1,11),(2,22);

=== modified file 'mysql-test/suite/innodb_plugin/r/innodb-index.result'
--- a/mysql-test/suite/innodb_plugin/r/innodb-index.result	2011-06-30 10:18:54 +0000
+++ b/mysql-test/suite/innodb_plugin/r/innodb-index.result	2011-07-05 22:56:51 +0000
@@ -1,3 +1,46 @@
+set global innodb_file_per_table=on;
+set global innodb_file_format='Barracuda';
+CREATE TABLE t1_purge (
+A INT,
+B BLOB, C BLOB, D BLOB, E BLOB,
+F BLOB, G BLOB, H BLOB,
+PRIMARY KEY (B(767), C(767), D(767), E(767), A),
+INDEX (A)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t1_purge VALUES (1,
+REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
+REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
+CREATE TABLE t2_purge (
+A INT PRIMARY KEY,
+B BLOB, C BLOB, D BLOB, E BLOB,
+F BLOB, G BLOB, H BLOB, I BLOB,
+J BLOB, K BLOB, L BLOB,
+INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t2_purge VALUES (1,
+REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
+REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
+REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
+CREATE TABLE t3_purge (
+A INT,
+B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
+F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
+PRIMARY KEY (B(767), C(767), D(767), E(767), A),
+INDEX (A)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t3_purge SELECT * FROM t1_purge;
+CREATE TABLE t4_purge (
+A INT PRIMARY KEY,
+B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
+F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
+J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
+INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t4_purge SELECT * FROM t2_purge;
+DELETE FROM t1_purge;
+DELETE FROM t2_purge;
+DELETE FROM t3_purge;
+DELETE FROM t4_purge;
+set global innodb_file_per_table=0;
+set global innodb_file_format=Antelope;
 create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
 insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
 commit;
@@ -1183,3 +1226,4 @@ a	b
 3	a
 3	b
 DROP TABLE t1;
+DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;

=== modified file 'mysql-test/suite/innodb_plugin/t/innodb-index.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb-index.test	2011-06-30 10:18:54 +0000
+++ b/mysql-test/suite/innodb_plugin/t/innodb-index.test	2011-07-05 22:56:51 +0000
@@ -4,6 +4,65 @@ let $MYSQLD_DATADIR= `select @@datadir`;
 
 let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
 
+let $per_table=`select @@innodb_file_per_table`;
+let $format=`select @@innodb_file_format`;
+set global innodb_file_per_table=on;
+set global innodb_file_format='Barracuda';
+
+# Test an assertion failure on purge.
+CREATE TABLE t1_purge (
+A INT,
+B BLOB, C BLOB, D BLOB, E BLOB,
+F BLOB, G BLOB, H BLOB,
+PRIMARY KEY (B(767), C(767), D(767), E(767), A),
+INDEX (A)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t1_purge VALUES (1,
+REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
+REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
+
+CREATE TABLE t2_purge (
+A INT PRIMARY KEY,
+B BLOB, C BLOB, D BLOB, E BLOB,
+F BLOB, G BLOB, H BLOB, I BLOB,
+J BLOB, K BLOB, L BLOB,
+INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t2_purge VALUES (1,
+REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
+REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
+REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
+
+CREATE TABLE t3_purge (
+A INT,
+B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
+F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
+PRIMARY KEY (B(767), C(767), D(767), E(767), A),
+INDEX (A)
+) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t3_purge SELECT * FROM t1_purge;
+
+CREATE TABLE t4_purge (
+A INT PRIMARY KEY,
+B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
+F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
+J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
+INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+
+INSERT INTO t4_purge SELECT * FROM t2_purge;
+
+# This would trigger the failure (Bug #12429576)
+# if purge gets a chance to run before DROP TABLE t1_purge, ....
+DELETE FROM t1_purge;
+DELETE FROM t2_purge;
+DELETE FROM t3_purge;
+DELETE FROM t4_purge;
+
+eval set global innodb_file_per_table=$per_table;
+eval set global innodb_file_format=$format;
+
 create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
 insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
 commit;
@@ -360,8 +419,6 @@ disconnect b;
 
 drop table t1;
 
-let $per_table=`select @@innodb_file_per_table`;
-let $format=`select @@innodb_file_format`;
 set global innodb_file_per_table=on;
 set global innodb_file_format='Barracuda';
 # Test creating a table that could lead to undo log overflow.
@@ -557,6 +614,7 @@ disconnect a;
 disconnect b;
 
 DROP TABLE t1;
+DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
 
 #
 # restore environment to the state it was before this test execution

=== modified file 'mysql-test/t/explain.test'
--- a/mysql-test/t/explain.test	2010-10-18 12:12:27 +0000
+++ b/mysql-test/t/explain.test	2011-05-04 15:12:45 +0000
@@ -1,5 +1,5 @@
 #
-# Test of different EXPLAIN's
+# Test of different EXPLAINs
 
 --disable_warnings
 drop table if exists t1;
@@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT);
 SELECT @@session.sql_mode INTO @old_sql_mode;
 SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
 
-# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE.
---error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
+# EXPLAIN EXTENDED (with subselect). used to crash.
+# This is actually a valid query for this sql_mode,
+# but it was transformed in such a way that it failed, see
+# Bug#12329653 - EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
 EXPLAIN EXTENDED SELECT 1 FROM t1
                           WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
-SHOW WARNINGS;
 
 SET SESSION sql_mode=@old_sql_mode;
 

=== added file 'mysql-test/t/secure_file_priv_win-master.opt'
--- a/mysql-test/t/secure_file_priv_win-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/secure_file_priv_win-master.opt	2011-04-28 09:22:41 +0000
@@ -0,0 +1 @@
+--secure_file_priv=$MYSQL_TMP_DIR

=== added file 'mysql-test/t/secure_file_priv_win.test'
--- a/mysql-test/t/secure_file_priv_win.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/secure_file_priv_win.test	2011-05-04 12:47:29 +0000
@@ -0,0 +1,79 @@
+#
+# Bug58747 breaks secure_file_priv+not secure yet+still accesses other folders
+#
+
+# we do the windows specific relative directory testing
+
+--source include/windows.inc
+
+CREATE TABLE t1 (c1 longtext);
+INSERT INTO t1 values ('a');
+
+LET $MYSQL_TMP_DIR_UCASE= `SELECT upper('$MYSQL_TMP_DIR')`;
+LET $MYSQL_TMP_DIR_LCASE= `SELECT lower('$MYSQL_TMP_DIR')`;
+
+#create the file
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517.tmp';
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+show global variables like 'secure_file_priv';
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT load_file('$MYSQL_TMP_DIR\\\\B11764517.tmp') AS x;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT load_file('$MYSQL_TMP_DIR/B11764517.tmp') AS x;
+
+--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
+eval SELECT load_file('$MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
+
+--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
+eval SELECT load_file('$MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT load_file('$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp') AS x;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval LOAD DATA INFILE '$MYSQL_TMP_DIR\\\\B11764517.tmp' INTO TABLE t1;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval LOAD DATA INFILE '$MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
+
+--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
+eval LOAD DATA INFILE '$MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
+
+--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
+eval LOAD DATA INFILE '$MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+--error ER_OPTION_PREVENTS_STATEMENT
+eval LOAD DATA INFILE "$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp" into table t1;
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+--error ER_OPTION_PREVENTS_STATEMENT
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517-2.tmp';
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\B11764517-2.tmp';
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517-3.tmp';
+
+--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
+
+--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
+eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
+
+--error 0,1
+--remove_file $MYSQL_TMP_DIR/B11764517.tmp;
+--error 0,1
+--remove_file $MYSQL_TMP_DIR/B11764517-2.tmp;
+--error 0,1
+--remove_file $MYSQL_TMP_DIR/B11764517-3.tmp;
+--error 0,1
+--remove_file $MYSQL_TMP_DIR/B11764517-4.tmp;
+--error 0,1
+--remove_file $MYSQL_TMP_DIR/B11764517-5.tmp;
+DROP TABLE t1;

=== modified file 'mysql-test/t/sp-security.test'
--- a/mysql-test/t/sp-security.test	2010-02-26 13:16:46 +0000
+++ b/mysql-test/t/sp-security.test	2011-04-13 07:57:16 +0000
@@ -926,6 +926,43 @@ DROP DATABASE B48872;
 
 --echo End of 5.0 tests.
 
+--echo #
+--echo # Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
+--echo #              DEFINITION OF ANY ROUTINE. 
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+--enable_warnings
+
+CREATE DATABASE db1;
+CREATE PROCEDURE db1.p1() SELECT 1;
+CREATE USER user2@localhost IDENTIFIED BY '';
+GRANT SELECT(db) ON mysql.proc TO user2@localhost;
+ 
+--echo # Connection con2 as user2
+connect (con2, localhost, user2);
+--echo # The statement below before disclosed info from body_utf8 column.
+--error ER_SP_DOES_NOT_EXIST
+SHOW CREATE PROCEDURE db1.p1;
+
+--echo # Check that SHOW works with SELECT grant on whole table
+--echo # Connection default
+connection default;
+GRANT SELECT ON mysql.proc TO user2@localhost;
+
+--echo # Connection con2
+connection con2;
+--echo # This should work
+SHOW CREATE PROCEDURE db1.p1;
+
+--echo # Connection default
+connection default;
+disconnect con2;
+DROP USER user2@localhost;
+DROP DATABASE db1;
+
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test	2011-04-14 14:35:24 +0000
+++ b/mysql-test/t/subselect.test	2011-05-10 13:57:40 +0000
@@ -3393,6 +3393,39 @@ ORDER BY outr.pk;
 
 DROP TABLE t1,t2;
 
+--echo #
+--echo # Bug#12329653 
+--echo # EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
+--echo #
+
+CREATE TABLE t1(a1 int);
+INSERT INTO t1 VALUES (1),(2);
+
+SELECT @@session.sql_mode INTO @old_sql_mode;
+SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
+
+## First a simpler query, illustrating the transformation
+## '1 < some (...)' => '1 < max(...)'
+SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
+
+## The query which made the server crash.
+PREPARE stmt FROM 
+'SELECT 1 UNION ALL 
+SELECT 1 FROM t1
+ORDER BY
+(SELECT 1 FROM t1 AS t1_0  
+  WHERE 1 < SOME (SELECT a1 FROM t1)
+)' ;
+
+--error ER_SUBQUERY_NO_1_ROW
+EXECUTE stmt ;
+--error ER_SUBQUERY_NO_1_ROW
+EXECUTE stmt ;
+
+SET SESSION sql_mode=@old_sql_mode;
+
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
 
 --echo End of 5.0 tests.
 

=== modified file 'mysys/my_symlink.c'
--- a/mysys/my_symlink.c	2011-06-30 15:37:13 +0000
+++ b/mysys/my_symlink.c	2011-07-05 22:56:51 +0000
@@ -146,24 +146,23 @@ int my_realpath(char *to, const char *fi
     result= -1;
   }
   DBUG_RETURN(result);
-#else
-#ifdef _WIN32
-  int ret= GetFullPathName(filename,FN_REFLEN,
-                           to,
-                           NULL);
+#elif defined(_WIN32)
+  int ret= GetFullPathName(filename,FN_REFLEN, to, NULL);
   if (ret == 0 || ret > FN_REFLEN)
   {
-    if (ret > FN_REFLEN)
-      my_errno= ENAMETOOLONG;
-    else
-      my_errno= EACCES;
+    my_errno= (ret > FN_REFLEN) ? ENAMETOOLONG : GetLastError();
     if (MyFlags & MY_WME)
       my_error(EE_REALPATH, MYF(0), filename, my_errno);
-	  return -1;
+    /* 
+      GetFullPathName didn't work : use my_load_path() which is a poor 
+      substitute original name but will at least be able to resolve 
+      paths that starts with '.'.
+    */  
+    my_load_path(to, filename, NullS);
+    return -1;
   }
 #else
   my_load_path(to, filename, NullS);
 #endif
   return 0;
-#endif
 }

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2011-07-03 15:47:37 +0000
+++ b/sql/item.cc	2011-07-05 22:56:51 +0000
@@ -4466,14 +4466,14 @@ mark_non_agg_field:
     SELECT_LEX *select_lex= cached_table ? 
       cached_table->select_lex : context->select_lex;
     if (!thd->lex->in_sum_func)
-      select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
+      select_lex->set_non_agg_field_used(true);
     else
     {
       if (outer_fixed)
         thd->lex->in_sum_func->outer_fields.push_back(this);
       else if (thd->lex->in_sum_func->nest_level !=
           thd->lex->current_select->nest_level)
-        select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
+        select_lex->set_non_agg_field_used(true);
     }
   }
   return FALSE;

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2011-07-03 15:47:37 +0000
+++ b/sql/item_subselect.cc	2011-07-05 22:56:51 +0000
@@ -1016,6 +1016,14 @@ Item_in_subselect::single_value_transfor
 	it.replace(item);
       }
 
+      DBUG_EXECUTE("where",
+                   print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
+      if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
+      {
+        DBUG_ASSERT(select_lex->non_agg_field_used());
+        select_lex->set_non_agg_field_used(false);
+      }
+
       save_allow_sum_func= thd->lex->allow_sum_func;
       thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
       /*

=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc	2011-07-03 15:47:37 +0000
+++ b/sql/item_sum.cc	2011-07-05 22:56:51 +0000
@@ -247,10 +247,10 @@ bool Item_sum::check_sum_func(THD *thd,
           in_sum_func->outer_fields.push_back(field);
         }
         else
-          sel->full_group_by_flag|= NON_AGG_FIELD_USED;
+          sel->set_non_agg_field_used(true);
       }
       if (sel->nest_level > aggr_level &&
-          (sel->full_group_by_flag & SUM_FUNC_USED) &&
+          (sel->agg_func_used()) &&
           !sel->group_list.elements)
       {
         my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
@@ -259,7 +259,7 @@ bool Item_sum::check_sum_func(THD *thd,
       }
     }
   }
-  aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
+  aggr_sel->set_agg_func_used(true);
   update_used_tables();
   thd->lex->in_sum_func= in_sum_func;
   return FALSE;

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2011-07-03 15:47:37 +0000
+++ b/sql/mysql_priv.h	2011-07-05 22:56:51 +0000
@@ -1476,13 +1476,6 @@ SQL_SELECT *make_select(TABLE *head, tab
 extern Item **not_found_item;
 
 /*
-  A set of constants used for checking non aggregated fields and sum
-  functions mixture in the ONLY_FULL_GROUP_BY_MODE.
-*/
-#define NON_AGG_FIELD_USED  1
-#define SUM_FUNC_USED       2
-
-/*
   This enumeration type is used only by the function find_item_in_list
   to return the info on how an item has been resolved against a list
   of possibly aliased items.

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-07-03 15:47:37 +0000
+++ b/sql/mysqld.cc	2011-07-05 22:56:51 +0000
@@ -8973,12 +8973,15 @@ fn_format_relative_to_data_home(char * t
 bool is_secure_file_path(char *path)
 {
   char buff1[FN_REFLEN], buff2[FN_REFLEN];
+  size_t opt_secure_file_priv_len;
   /*
     All paths are secure if opt_secure_file_path is 0
   */
   if (!opt_secure_file_priv)
     return TRUE;
 
+  opt_secure_file_priv_len= strlen(opt_secure_file_priv);
+
   if (strlen(path) >= FN_REFLEN)
     return FALSE;
 
@@ -8996,11 +8999,24 @@ bool is_secure_file_path(char *path)
       return FALSE;
   }
   convert_dirname(buff2, buff1, NullS);
-  if (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
-    return FALSE;
+  if (!lower_case_file_system)
+  {
+    if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
+      return FALSE;
+  }
+  else
+  {
+    if (files_charset_info->coll->strnncoll(files_charset_info,
+                                            (uchar *) buff2, strlen(buff2),
+                                            (uchar *) opt_secure_file_priv,
+                                            opt_secure_file_priv_len,
+                                            TRUE))
+      return FALSE;
+  }
   return TRUE;
 }
 
+
 static int fix_paths(void)
 {
   char buff[FN_REFLEN],*pos;

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2011-07-03 15:47:37 +0000
+++ b/sql/sp_head.cc	2011-07-05 22:56:51 +0000
@@ -2403,7 +2403,8 @@ bool check_show_routine_access(THD *thd,
   bzero((char*) &tables,sizeof(tables));
   tables.db= (char*) "mysql";
   tables.table_name= tables.alias= (char*) "proc";
-  *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) ||
+  *full_access= ((!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) &&
+                  (tables.grant.privilege & SELECT_ACL) != 0) ||
                  (!strcmp(sp->m_definer_user.str,
                           thd->security_ctx->priv_user) &&
                   !strcmp(sp->m_definer_host.str,

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2011-07-03 15:47:37 +0000
+++ b/sql/sql_connect.cc	2011-07-05 22:56:51 +0000
@@ -21,23 +21,10 @@
 
 #include "mysql_priv.h"
 
-#ifdef HAVE_OPENSSL
-/*
-  Without SSL the handshake consists of one packet. This packet
-  has both client capabilites and scrambled password.
-  With SSL the handshake might consist of two packets. If the first
-  packet (client capabilities) has CLIENT_SSL flag set, we have to
-  switch to SSL and read the second packet. The scrambled password
-  is in the second packet and client_capabilites field will be ignored.
-  Maybe it is better to accept flags other than CLIENT_SSL from the
-  second packet?
-*/
-#define SSL_HANDSHAKE_SIZE      2
-#define NORMAL_HANDSHAKE_SIZE   6
-#define MIN_HANDSHAKE_SIZE      2
-#else
-#define MIN_HANDSHAKE_SIZE      6
-#endif /* HAVE_OPENSSL */
+/** Size of the header fields of an authentication packet. */
+#define AUTH_PACKET_HEADER_SIZE_PROTO_41    32
+#define AUTH_PACKET_HEADER_SIZE_PROTO_40    5  
+#define AUTH_PACKET_HEADER_SIZE_CONNJ_SSL   4
 
 #ifdef __WIN__
 extern void win_install_sigabrt_handler();
@@ -822,6 +809,14 @@ static int check_connection(THD *thd)
   ulong pkt_len= 0;
   char *end;
 
+  bool packet_has_required_size= false;
+  char *db;
+  size_t db_len;
+  char *passwd;
+  size_t passwd_len;
+  char *user;
+  size_t user_len;
+
   DBUG_PRINT("info",
              ("New connection received on %s", vio_description(net->vio)));
 #ifdef SIGNAL_WITH_VIO_CLOSE
@@ -930,8 +925,7 @@ static int check_connection(THD *thd)
     /* At this point we write connection message and read reply */
     if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
                           (uchar*) buff, (size_t) (end-buff)) ||
-	(pkt_len= my_net_read(net)) == packet_error ||
-	pkt_len < MIN_HANDSHAKE_SIZE)
+	(pkt_len= my_net_read(net)) == packet_error)
     {
       inc_host_errors(&thd->remote.sin_addr);
       my_error(ER_HANDSHAKE_ERROR, MYF(0));
@@ -946,22 +940,82 @@ static int check_connection(THD *thd)
   if (thd->packet.alloc(thd->variables.net_buffer_length))
     return 1; /* The error is set by alloc(). */
 
-  thd->client_capabilities= uint2korr(net->read_pos);
+  uint charset_code= 0;
+  end= (char *)net->read_pos;
+  /*
+    In order to safely scan a head for '\0' string terminators
+    we must keep track of how many bytes remain in the allocated
+    buffer or we might read past the end of the buffer.
+  */
+  size_t bytes_remaining_in_packet= pkt_len;
+  
+  /*
+    Peek ahead on the client capability packet and determine which version of
+    the protocol should be used.
+  */
+  if (bytes_remaining_in_packet < 2)
+    goto error;
+  
+  thd->client_capabilities= uint2korr(end);
+
+  /*
+    Connector/J only sends client capabilities (4 bytes) before starting SSL
+    negotiation so we don't have char_set and other information for client in
+    packet read. In that case, skip reading those information. The below code 
+    is patch for this.
+  */
+  if(bytes_remaining_in_packet == AUTH_PACKET_HEADER_SIZE_CONNJ_SSL &&
+     (thd->client_capabilities & CLIENT_SSL))
+  {
+    thd->client_capabilities= uint4korr(end);
+    thd->max_client_packet_length= global_system_variables.max_allowed_packet;
+    charset_code= default_charset_info->number;
+    end+= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
+    bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
+    goto skip_to_ssl;
+  }
+
+  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+    packet_has_required_size= bytes_remaining_in_packet >= 
+      AUTH_PACKET_HEADER_SIZE_PROTO_41;
+  else
+    packet_has_required_size= bytes_remaining_in_packet >=
+      AUTH_PACKET_HEADER_SIZE_PROTO_40;
+  
+  if (!packet_has_required_size)
+    goto error;
+  
   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
   {
-    thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
-    thd->max_client_packet_length= uint4korr(net->read_pos+4);
-    DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
-    if (thd_init_client_charset(thd, (uint) net->read_pos[8]))
-      return 1;
-    thd->update_charset();
-    end= (char*) net->read_pos+32;
+    thd->client_capabilities= uint4korr(end);
+    thd->max_client_packet_length= uint4korr(end + 4);
+    charset_code= (uint)(uchar)*(end + 8);
+    /*
+      Skip 23 remaining filler bytes which have no particular meaning.
+    */
+    end+= AUTH_PACKET_HEADER_SIZE_PROTO_41;
+    bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_41;
   }
   else
   {
-    thd->max_client_packet_length= uint3korr(net->read_pos+2);
-    end= (char*) net->read_pos+5;
+    thd->client_capabilities= uint2korr(end);
+    thd->max_client_packet_length= uint3korr(end + 2);
+    end+= AUTH_PACKET_HEADER_SIZE_PROTO_40;
+    bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_40;
+    /**
+      Old clients didn't have their own charset. Instead the assumption
+      was that they used what ever the server used.
+    */
+    charset_code= default_charset_info->number;
   }
+
+skip_to_ssl:
+
+  DBUG_PRINT("info", ("client_character_set: %u", charset_code));
+  if (thd_init_client_charset(thd, charset_code))
+    goto error;
+  thd->update_charset();
+
   /*
     Disable those bits which are not supported by the server.
     This is a precautionary measure, if the client lies. See Bug#27944.
@@ -972,42 +1026,63 @@ static int check_connection(THD *thd)
     thd->variables.sql_mode|= MODE_IGNORE_SPACE;
 #ifdef HAVE_OPENSSL
   DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
+  
+  /*
+    If client requested SSL then we must stop parsing, try to switch to SSL,
+    and wait for the client to send a new handshake packet.
+    The client isn't expected to send any more bytes until SSL is initialized.
+  */
   if (thd->client_capabilities & CLIENT_SSL)
   {
     /* Do the SSL layering. */
     if (!ssl_acceptor_fd)
-    {
-      inc_host_errors(&thd->remote.sin_addr);
-      my_error(ER_HANDSHAKE_ERROR, MYF(0));
-      return 1;
-    }
+      goto error;
+
     DBUG_PRINT("info", ("IO layer change in progress..."));
     if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
     {
       DBUG_PRINT("error", ("Failed to accept new SSL connection"));
-      inc_host_errors(&thd->remote.sin_addr);
-      my_error(ER_HANDSHAKE_ERROR, MYF(0));
-      return 1;
+      goto error;
     }
+    
     DBUG_PRINT("info", ("Reading user information over SSL layer"));
-    if ((pkt_len= my_net_read(net)) == packet_error ||
-	pkt_len < NORMAL_HANDSHAKE_SIZE)
+    if ((pkt_len= my_net_read(net)) == packet_error)
     {
       DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
 			   pkt_len));
-      inc_host_errors(&thd->remote.sin_addr);
-      my_error(ER_HANDSHAKE_ERROR, MYF(0));
-      return 1;
+      goto error;
     }
-  }
-#endif /* HAVE_OPENSSL */
+    /*
+      A new packet was read and the statistics reflecting the remaining bytes
+      in the packet must be updated.
+    */
+    bytes_remaining_in_packet= pkt_len;
 
-  if (end > (char *)net->read_pos + pkt_len)
-  {
-    inc_host_errors(&thd->remote.sin_addr);
-    my_error(ER_HANDSHAKE_ERROR, MYF(0));
-    return 1;
+    /*
+      After the SSL handshake is performed the client resends the handshake
+      packet but because of legacy reasons we chose not to parse the packet
+      fields a second time and instead only assert the length of the packet.
+    */
+    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+    {
+      
+      packet_has_required_size= bytes_remaining_in_packet >= 
+        AUTH_PACKET_HEADER_SIZE_PROTO_41;
+      end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_41;
+      bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_41;
+    }
+    else
+    {
+      packet_has_required_size= bytes_remaining_in_packet >= 
+        AUTH_PACKET_HEADER_SIZE_PROTO_40;
+      end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_40;
+      bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_40;
+    }
+  
+    if (!packet_has_required_size)
+      goto error;
   }
+#endif /* HAVE_OPENSSL */
 
   if (thd->client_capabilities & CLIENT_INTERACTIVE)
     thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
@@ -1028,29 +1103,17 @@ static int check_connection(THD *thd)
   else
     get_string= get_40_protocol_string;
 
-  /*
-    In order to safely scan a head for '\0' string terminators
-    we must keep track of how many bytes remain in the allocated
-    buffer or we might read past the end of the buffer.
-  */
-  size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
-
-  size_t user_len;
-  char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
+  user= get_string(&end, &bytes_remaining_in_packet, &user_len);
   if (user == NULL)
-  {
-    inc_host_errors(&thd->remote.sin_addr);
-    my_error(ER_HANDSHAKE_ERROR, MYF(0));
-    return 1;
-  }
+    goto error;
 
   /*
     Old clients send a null-terminated string as password; new clients send
     the size (1 byte) + string (not null-terminated). Hence in case of empty
     password both send '\0'.
   */
-  size_t passwd_len= 0;
-  char *passwd= NULL;
+  passwd_len= 0;
+  passwd= NULL;
 
   if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
   {
@@ -1069,24 +1132,16 @@ static int check_connection(THD *thd)
   }
 
   if (passwd == NULL)
-  {
-    inc_host_errors(&thd->remote.sin_addr);
-    my_error(ER_HANDSHAKE_ERROR, MYF(0));
-    return 1;
-  }
+    goto error;
 
-  size_t db_len= 0;
-  char *db= NULL;
+  db_len= 0;
+  db= NULL;
 
   if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
   {
     db= get_string(&end, &bytes_remaining_in_packet, &db_len);
     if (db == NULL)
-    {
-      inc_host_errors(&thd->remote.sin_addr);
-      my_error(ER_HANDSHAKE_ERROR, MYF(0));
-      return 1;
-    }
+      goto error;
   }
 
   char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
@@ -1134,11 +1189,14 @@ static int check_connection(THD *thd)
     user[user_len]= '\0';
   }
 
-  if (thd->main_security_ctx.user)
-    x_free(thd->main_security_ctx.user);
   if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
     return 1; /* The error is set by my_strdup(). */
   return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
+  
+error:
+  inc_host_errors(&thd->remote.sin_addr);
+  my_error(ER_HANDSHAKE_ERROR, MYF(0));
+  return 1;
 }
 
 
@@ -1388,3 +1446,4 @@ end_thread:
   }
 }
 #endif /* EMBEDDED_LIBRARY */
+

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2011-07-03 15:47:37 +0000
+++ b/sql/sql_lex.cc	2011-07-05 22:56:51 +0000
@@ -1623,6 +1623,8 @@ void st_select_lex::init_query()
   nest_level= 0;
   link_next= 0;
   lock_option= TL_READ_DEFAULT;
+  m_non_agg_field_used= false;
+  m_agg_func_used= false;
 }
 
 void st_select_lex::init_select()
@@ -1653,7 +1655,8 @@ void st_select_lex::init_select()
   non_agg_fields.empty();
   cond_value= having_value= Item::COND_UNDEF;
   inner_refs_list.empty();
-  full_group_by_flag= 0;
+  m_non_agg_field_used= false;
+  m_agg_func_used= false;
 }
 
 /*

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2011-07-03 15:47:37 +0000
+++ b/sql/sql_lex.h	2011-07-05 22:56:51 +0000
@@ -715,16 +715,7 @@ public:
     joins on the right.
   */
   List<String> *prev_join_using;
-  /*
-    Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate
-    functions and non aggregated fields when GROUP BY list is absent.
-    Bits:
-      0 - non aggregated fields are used in this select,
-          defined as NON_AGG_FIELD_USED.
-      1 - aggregate functions are used in this select,
-          defined as SUM_FUNC_USED.
-  */
-  uint8 full_group_by_flag;
+
   void init_query();
   void init_select();
   st_select_lex_unit* master_unit();
@@ -832,7 +823,22 @@ public:
 
   void clear_index_hints(void) { index_hints= NULL; }
 
-private:  
+  /*
+    For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
+     - Non-aggregated fields are used in this select.
+     - Aggregate functions are used in this select.
+    In MODE_ONLY_FULL_GROUP_BY only one of these may be true.
+  */
+  bool non_agg_field_used() const { return m_non_agg_field_used; }
+  bool agg_func_used()      const { return m_agg_func_used; }
+
+  void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
+  void set_agg_func_used(bool val)      { m_agg_func_used= val; }
+
+private:
+  bool m_non_agg_field_used;
+  bool m_agg_func_used;
+
   /* current index hint kind. used in filling up index_hints */
   enum index_hint_type current_index_hint_type;
   index_clause_map current_index_hint_clause;

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2011-07-03 15:47:37 +0000
+++ b/sql/sql_load.cc	2011-07-05 22:56:51 +0000
@@ -350,21 +350,21 @@ int mysql_load(THD *thd,sql_exchange *ex
 
 #if !defined(__WIN__) && ! defined(__NETWARE__)
     MY_STAT stat_info;
-    if (!my_stat(name,&stat_info,MYF(MY_WME)))
-	    DBUG_RETURN(TRUE);
+    if (!my_stat(name, &stat_info, MYF(MY_WME)))
+      DBUG_RETURN(TRUE);
 
     // if we are not in slave thread, the file must be:
     if (!thd->slave_thread &&
-	      !((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
-	        (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
-	        ((stat_info.st_mode & S_IFREG) == S_IFREG ||
-	         (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
+        !((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
+          (stat_info.st_mode & S_IFLNK) != S_IFLNK &&  // and not a symlink
+          ((stat_info.st_mode & S_IFREG) == S_IFREG || // and a regular file
+           (stat_info.st_mode & S_IFIFO) == S_IFIFO))) // or FIFO
     {
-	    my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
-	    DBUG_RETURN(TRUE);
+      my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
+      DBUG_RETURN(TRUE);
     }
     if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
-	    is_fifo = 1;
+      is_fifo= 1;
 #endif
 
     if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2011-05-16 20:04:01 +0000
+++ b/sql/sql_partition.cc	2011-06-06 13:53:46 +0000
@@ -930,9 +930,6 @@ static bool fix_fields_part_func(THD *th
   const char *save_where;
   char* db_name;
   char db_name_string[FN_REFLEN];
-  bool save_use_only_table_context;
-  uint8 saved_full_group_by_flag;
-  nesting_map saved_allow_sum_func;
   DBUG_ENTER("fix_fields_part_func");
 
   if (part_info->fixed)
@@ -999,23 +996,26 @@ static bool fix_fields_part_func(THD *th
     of interesting side effects, both desirable and undesirable.
   */
 
-  save_use_only_table_context= thd->lex->use_only_table_context;
-  thd->lex->use_only_table_context= TRUE;
-  thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
-  saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag;
-  saved_allow_sum_func= thd->lex->allow_sum_func;
-  thd->lex->allow_sum_func= 0;
+  {
+    const bool save_use_only_table_context= thd->lex->use_only_table_context;
+    thd->lex->use_only_table_context= TRUE;
+    thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
+    const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
+    const bool save_agg_func=  thd->lex->current_select->agg_func_used();
+    const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
+    thd->lex->allow_sum_func= 0;
   
-  error= func_expr->fix_fields(thd, (Item**)&func_expr);
+    error= func_expr->fix_fields(thd, (Item**)&func_expr);
 
-  /*
-    Restore full_group_by_flag and allow_sum_func,
-    fix_fields should not affect mysql_select later, see Bug#46923.
-  */
-  thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag;
-  thd->lex->allow_sum_func= saved_allow_sum_func;
-
-  thd->lex->use_only_table_context= save_use_only_table_context;
+    /*
+      Restore agg_field/agg_func and allow_sum_func,
+      fix_fields should not affect mysql_select later, see Bug#46923.
+    */
+    thd->lex->current_select->set_non_agg_field_used(save_agg_field);
+    thd->lex->current_select->set_agg_func_used(save_agg_func);
+    thd->lex->allow_sum_func= saved_allow_sum_func;
+    thd->lex->use_only_table_context= save_use_only_table_context;
+  }
 
   context->table_list= save_table_list;
   context->first_name_resolution_table= save_first_table;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-07-03 15:47:37 +0000
+++ b/sql/sql_select.cc	2011-07-05 22:56:51 +0000
@@ -426,19 +426,18 @@ inline int setup_without_group(THD *thd,
   int res;
   nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
   /* 
-    Need to save the value, so we can turn off only the new NON_AGG_FIELD
+    Need to save the value, so we can turn off only any new non_agg_field_used
     additions coming from the WHERE
   */
-  uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
+  const bool saved_non_agg_field_used=
+    thd->lex->current_select->non_agg_field_used();
   DBUG_ENTER("setup_without_group");
 
   thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
   res= setup_conds(thd, tables, leaves, conds);
 
   /* it's not wrong to have non-aggregated columns in a WHERE */
-  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
-    thd->lex->current_select->full_group_by_flag= saved_flag |
-      (thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
+  thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
 
   thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
   res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
@@ -644,7 +643,8 @@ JOIN::prepare(Item ***rref_pointer_array
     aggregate functions with implicit grouping (there is no GROUP BY).
   */
   if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
-      select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED))
+      select_lex->non_agg_field_used() &&
+      select_lex->agg_func_used())
   {
     my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
                ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));

=== modified file 'storage/innodb_plugin/ChangeLog'
--- a/storage/innodb_plugin/ChangeLog	2011-06-30 10:18:54 +0000
+++ b/storage/innodb_plugin/ChangeLog	2011-07-05 22:56:51 +0000
@@ -37,6 +37,11 @@
 	* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
 	Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
 
+2011-05-19	The InnoDB Team
+
+	* row/row0row.c:
+	Fix Bug#12429576 Assertion failure on purge of column prefix index
+
 2011-04-07	The InnoDB Team
 
 	* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:

=== modified file 'storage/innodb_plugin/row/row0row.c'
--- a/storage/innodb_plugin/row/row0row.c	2011-06-30 10:18:54 +0000
+++ b/storage/innodb_plugin/row/row0row.c	2011-07-05 22:56:51 +0000
@@ -156,8 +156,6 @@ row_build_index_entry(
 			each off-page column. */
 			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 			len -= BTR_EXTERN_FIELD_REF_SIZE;
-			ut_a(ind_field->prefix_len <= len
-			     || dict_index_is_clust(index));
 		}
 
 		/* If a column prefix index, take only the prefix. */

=== removed directory 'storage/ndb/test/sql'
=== removed file 'storage/ndb/test/sql/BANK.sql'
--- a/storage/ndb/test/sql/BANK.sql	2011-06-30 15:37:13 +0000
+++ b/storage/ndb/test/sql/BANK.sql	1970-01-01 00:00:00 +0000
@@ -1,60 +0,0 @@
--- Copyright (c) 2005 MySQL AB
--- Use is subject to license terms.
---
--- This program is free software; you can redistribute it and/or modify
--- it under the terms of the GNU General Public License as published by
--- the Free Software Foundation; version 2 of the License.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program; if not, write to the Free Software
--- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
-
-CREATE DATABASE IF NOT EXISTS BANK default charset=latin1 default collate=latin1_bin;
-USE BANK;
-DROP TABLE IF EXISTS GL;
-CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
-                  ACCOUNT_TYPE INT UNSIGNED NOT NULL,
-                  BALANCE INT UNSIGNED NOT NULL,
-                  DEPOSIT_COUNT INT UNSIGNED NOT NULL,
-                  DEPOSIT_SUM INT UNSIGNED NOT NULL,
-                  WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
-                  WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
-                  PURGED INT UNSIGNED NOT NULL,
-                  PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
-   ENGINE = NDB;
-
-DROP TABLE IF EXISTS ACCOUNT;
-CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
-                       OWNER INT UNSIGNED NOT NULL,
-                       BALANCE INT UNSIGNED NOT NULL,
-                       ACCOUNT_TYPE INT UNSIGNED NOT NULL,
-                       PRIMARY KEY USING HASH (ACCOUNT_ID))
-   ENGINE = NDB;
-
-DROP TABLE IF EXISTS TRANSACTION;
-CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
-                           ACCOUNT INT UNSIGNED NOT NULL,
-                           ACCOUNT_TYPE INT UNSIGNED NOT NULL,
-                           OTHER_ACCOUNT INT UNSIGNED NOT NULL,
-                           TRANSACTION_TYPE INT UNSIGNED NOT NULL,
-                           TIME BIGINT UNSIGNED NOT NULL,
-                           AMOUNT INT UNSIGNED NOT NULL,
-                           PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
-   ENGINE = NDB;
-
-DROP TABLE IF EXISTS SYSTEM_VALUES;
-CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
-                             VALUE BIGINT UNSIGNED NOT NULL,
-                             PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
-   ENGINE = NDB;
-
-DROP TABLE IF EXISTS ACCOUNT_TYPE;
-CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
-                            DESCRIPTION CHAR(64) NOT NULL,
-                            PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
-   ENGINE = NDB;

=== removed file 'storage/ndb/test/sql/T1.sql'
--- a/storage/ndb/test/sql/T1.sql	2011-06-30 15:37:13 +0000
+++ b/storage/ndb/test/sql/T1.sql	1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
--- Copyright (c) 2005 MySQL AB
--- Use is subject to license terms.
---
--- This program is free software; you can redistribute it and/or modify
--- it under the terms of the GNU General Public License as published by
--- the Free Software Foundation; version 2 of the License.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program; if not, write to the Free Software
--- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
-
-create database if not exists TEST_DB;
-use TEST_DB;
-drop table if exists T1;
-create table T1 (KOL1 int unsigned not null,
-                 KOL2 int unsigned not null,
-	         KOL3 int unsigned not null,
-	         KOL4 int unsigned not null,
-	         KOL5 int unsigned not null,
-	         primary key using hash(KOL1)) engine=ndb;

=== removed file 'storage/ndb/test/sql/test_create_drop.pl'
--- a/storage/ndb/test/sql/test_create_drop.pl	2010-12-28 23:47:05 +0000
+++ b/storage/ndb/test/sql/test_create_drop.pl	1970-01-01 00:00:00 +0000
@@ -1,196 +0,0 @@
-# Copyright (C) 2005 MySQL AB
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; version 2
-# of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the Free
-# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-# MA 02111-1307, USA
-
-use strict;
-use IO::Socket;
-use DBI;
-
-# mgm info
-my $mgmhost = "localhost";
-my $mgmport = 38101;
-
-# location of ndb_x_fs
-my $datadir = "c2";
-my @schemafiles = <$datadir/ndb_*_fs/D[12]/DBDICT/P0.SchemaLog>;
-@schemafiles or die "no schemafiles in $datadir";
-
-my $dsn;
-$dsn = "dbi:mysql:test:localhost;port=38100";
-
-# this works better for me
-my $cnf = $ENV{MYSQL_HOME} . "/var/my.cnf";
-$dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$cnf";
-
-my $dbh;
-$dbh = DBI->connect($dsn, 'root', undef, { RaiseError => 0, PrintError => 0 });
-$dbh or die $DBI::errstr;
-
-# mgm commands
-
-my $mgm = undef;
-
-sub mgmconnect {
-  $mgm = IO::Socket::INET->new(
-    Proto => "tcp",
-    PeerHost => $mgmhost,
-    PeerPort => $mgmport);
-  $mgm or die "connect to mgm failed: $!";
-  $mgm->autoflush(1);
-};
-
-mgmconnect();
-warn "connected to mgm $mgmhost $mgmport\n";
-
-my $nodeinfo = {};
-
-sub getnodeinfo {
-  $nodeinfo = {};
-  $mgm->print("get status\n");
-  $mgm->print("\n");
-  while (defined($_ = $mgm->getline)) {
-    /^node\s+status/ && last;
-  }
-  while (defined($_ = $mgm->getline)) {
-    /^\s*$/ && last;
-    /^node\.(\d+)\.(\w+):\s*(\S+)/ && ($nodeinfo->{$1}{$2} = $3);
-  }
-}
-
-getnodeinfo();
-
-my @dbnode = ();
-for my $n (keys %$nodeinfo) {
-  my $p = $nodeinfo->{$n};
-  ($p->{type} eq 'NDB') && push(@dbnode, $n);
-}
-@dbnode = sort { $a <=> $b } @dbnode;
-@dbnode or die "mgm error, found no db nodes";
-warn "db nodes: @dbnode\n";
-
-sub restartnode {
-  my($n, $initialstart) = @_;
-  warn "restart node $n initialstart=$initialstart\n";
-  $mgm->print("restart node\n");
-  $mgm->print("node: $n\n");
-  $mgm->print("initialstart: $initialstart\n");
-  $mgm->print("\n");
-  while (1) {
-    sleep 5;
-    getnodeinfo();
-    my $status = $nodeinfo->{$n}{status};
-    my $sp = $nodeinfo->{$n}{startphase};
-    warn "node $n status: $status sp: $sp\n";
-    last if $status eq 'STARTED';
-  }
-}
-
-sub restartall {
-  warn "restart all\n";
-  $mgm->print("restart all\n");
-  $mgm->print("\n");
-  while (1) {
-    sleep 5;
-    getnodeinfo();
-    my $ok = 1;
-    for my $n (@dbnode) {
-      my $status = $nodeinfo->{$n}{status};
-      my $sp = $nodeinfo->{$n}{startphase};
-      warn "node $n status: $status sp: $sp\n";
-      $ok = 0 if $status ne 'STARTED';
-    }
-    last if $ok;
-  }
-}
-
-# the sql stuff
-
-my $maxtab = 300;
-my @tab = ();
-
-sub create {
-  my($n) = @_;
-  my $sql = "create table t$n (a int primary key, b varchar(20), key (b)) engine=ndb";
-  warn "create t$n\n";
-  $dbh->do($sql) or die "$sql\n$DBI::errstr";
-}
-
-sub drop {
-  my($n) = @_;
-  my $sql = "drop table t$n";
-  warn "drop t$n\n";
-  $dbh->do($sql) or die "$sql\n$DBI::errstr";
-}
-
-sub dropall {
-  for my $n (0..($maxtab-1)) {
-    my $sql = "drop table if exists t$n";
-    $dbh->do($sql) or die "$sql\n$DBI::errstr";
-  }
-}
-
-sub createdrop {
-  my $n = int(rand($maxtab));
-  if (! $tab[$n]) {
-    create($n);
-    $tab[$n] = 1;
-  } else {
-    drop($n);
-    $tab[$n] = 0;
-  }
-}
-
-sub checkschemafiles {
-  system("printSchemaFile -ce @schemafiles");
-  $? == 0 or die "schemafiles check failed";
-}
-
-sub randomrestart {
-  my($k) = @_;
-  my $s = int(rand(500));
-  if ($s < 2) {
-    my $i = $k % scalar(@dbnode);
-    my $n = $dbnode[$i];
-    my $initialstart = ($s < 1 ? 0 : 1);
-    restartnode($n, $initialstart);
-    return 1;
-  }
-  if ($s < 3) {
-    restartall();
-    return 1;
-  }
-  return 0;
-}
-
-# deterministic
-srand(1);
-
-warn "drop any old tables\n";
-dropall();
-
-my $loop = 1000000;
-for my $k (0..($loop-1)) {
-  warn "$k\n";
-  createdrop();
-  checkschemafiles();
-  if (randomrestart($k)) {
-    checkschemafiles();
-  }
-}
-
-$dbh->disconnect or die $DBI::errstr;
-
-# vim: set sw=2:

=== removed file 'storage/ndb/test/sql/test_range_bounds.pl'
--- a/storage/ndb/test/sql/test_range_bounds.pl	2010-12-28 23:47:05 +0000
+++ b/storage/ndb/test/sql/test_range_bounds.pl	1970-01-01 00:00:00 +0000
@@ -1,235 +0,0 @@
-# Copyright (C) 2005 MySQL AB
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; version 2
-# of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the Free
-# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-# MA 02111-1307, USA
-
-#
-# test range scan bounds
-# give option --all to test all cases
-# set MYSQL_HOME to installation top
-#
-
-use strict;
-use integer;
-use Getopt::Long;
-use DBI;
-
-my $opt_all = 0;
-my $opt_cnt = 5;
-my $opt_verbose = 0;
-GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
-  or die "options are:  --all --cnt=N --verbose";
-
-my $mysql_home = $ENV{MYSQL_HOME};
-defined($mysql_home) or die "no MYSQL_HOME";
-my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
-my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
-
-my $dbh;
-my $sth;
-my $sql;
-
-$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
-
-my $table = 't';
-
-$sql = "drop table if exists $table";
-$dbh->do($sql) or die $DBI::errstr;
-
-sub cut ($$$) {
-  my($op, $key, $val) = @_;
-  $op = '==' if $op eq '=';
-  my(@w) = @$val;
-  eval "\@w = grep(\$_ $op $key, \@w)";
-  $@ and die $@;
-  return [ @w ];
-}
-
-sub mkdummy ($) {
-  my ($val) = @_;
-  return {
-    'dummy' => 1,
-    'exp' => '9 = 9',
-    'res' => $val,
-  };
-}
-
-sub mkone ($$$$) {
-  my($col, $op, $key, $val) = @_;
-  my $res = cut($op, $key, $val);
-  return {
-    'exp' => "$col $op $key",
-    'res' => $res,
-  };
-}
-
-sub mktwo ($$$$$$) {
-  my($col, $op1, $key1, $op2, $key2, $val) = @_;
-  my $res = cut($op2, $key2, cut($op1, $key1, $val));
-  return {
-    'exp' => "$col $op1 $key1 and $col $op2 $key2",
-    'res' => $res,
-  };
-}
-
-sub mkall ($$$$) {
-  my($col, $key1, $key2, $val) = @_;
-  my @a = ();
-  my $p = mkdummy($val);
-  push(@a, $p) if $opt_all;
-  my @ops = qw(< <= = >= >);
-  for my $op (@ops) {
-    my $p = mkone($col, $op, $key1, $val);
-    push(@a, $p) if $opt_all || @{$p->{res}} != 0;
-  }
-  my @ops1 = $opt_all ? @ops : qw(= >= >);
-  my @ops2 = $opt_all ? @ops : qw(<= <);
-  for my $op1 (@ops1) {
-    for my $op2 (@ops2) {
-      my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
-      push(@a, $p) if $opt_all || @{$p->{res}} != 0;
-    }
-  }
-  warn scalar(@a)." cases\n" if $opt_verbose;
-  return \@a;
-}
-
-my $casecnt = 0;
-
-sub verify ($$$) {
-  my($sql, $ord, $res) = @_;
-  warn "$sql\n" if $opt_verbose;
-  $sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
-  $sth->execute() or die "execute: $sql: $DBI::errstr";
-  #
-  # BUG: execute can return success on error so check again
-  #
-  $sth->err and die "execute: $sql: $DBI::errstr";
-  my @out = ();
-  for my $b (@{$res->[0]}) {
-    for my $c (@{$res->[1]}) {
-      for my $d (@{$res->[2]}) {
-	push(@out, [$b, $c, $d]);
-      }
-    }
-  }
-  if ($ord) {
-    @out = sort {
-      $ord * ($a->[0] - $b->[0]) ||
-      $ord * ($a->[1] - $b->[1]) ||
-      $ord * ($a->[2] - $b->[2]) ||
-      0
-    } @out;
-  }
-  my $cnt = scalar @out;
-  my $n = 0;
-  while (1) {
-    my $row = $sth->fetchrow_arrayref;
-    $row || last;
-    @$row == 3 or die "bad row: $sql:  @$row";
-    for my $v (@$row) {
-      $v =~ s/^\s+|\s+$//g;
-      $v =~ /^\d+$/ or die "bad value: $sql:  $v";
-    }
-    if ($ord) {
-      my $out = $out[$n];
-      $row->[0] == $out->[0] &&
-      $row->[1] == $out->[1] &&
-      $row->[2] == $out->[2] or
-        die "$sql: row $n: got row @$row != @$out";
-    }
-    $n++;
-  }
-  $sth->err and die "fetch: $sql: $DBI::errstr";
-  $n == $cnt or die "verify: $sql: got row count $n != $cnt";
-  $casecnt++;
-}
-
-for my $nn ("bcd", "") {
-  my %nn;
-  for my $x (qw(b c d)) {
-    $nn{$x} = $nn =~ /$x/ ? "not null" : "null";
-  }
-  warn "create table\n";
-  $sql = <<EOF;
-create table $table (
-  a int primary key,
-  b int $nn{b},
-  c int $nn{c},
-  d int $nn{d},
-  index (b, c, d)
-) engine=ndb
-EOF
-  $dbh->do($sql) or die $DBI::errstr;
-  warn "insert\n";
-  $sql = "insert into $table values(?, ?, ?, ?)";
-  $sth = $dbh->prepare($sql) or die $DBI::errstr;
-  my @val = (0..($opt_cnt-1));
-  my $v0 = 0;
-  for my $v1 (@val) {
-    for my $v2 (@val) {
-      for my $v3 (@val) {
-	$sth->bind_param(1, $v0) or die $DBI::errstr;
-	$sth->bind_param(2, $v1) or die $DBI::errstr;
-	$sth->bind_param(3, $v2) or die $DBI::errstr;
-	$sth->bind_param(4, $v3) or die $DBI::errstr;
-	$sth->execute or die $DBI::errstr;
-	$v0++;
-      }
-    }
-  }
-  warn "generate cases\n";
-  my $key1 = 1;
-  my $key2 = 3;
-  my $a1 = mkall('b', $key1, $key2, \@val);
-  my $a2 = mkall('c', $key1, $key2, \@val);
-  my $a3 = mkall('d', $key1, $key2, \@val);
-  warn "select\n";
-  for my $ord (0, +1, -1) {
-    my $orderby =
-      $ord == 0 ? "" :
-      $ord == +1 ? " order by b, c, d" :
-      $ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
-    for my $p1 (@$a1) {
-      my $res = [ $p1->{res}, \@val, \@val ];
-      $sql = "select b, c, d from $table" .
-	     " where $p1->{exp}" .
-	     $orderby;
-      verify($sql, $ord, $res);
-      for my $p2 (@$a2) {
-	my $res = [ $p1->{res}, $p2->{res}, \@val ];
-	$sql = "select b, c, d from $table" .
-	       " where $p1->{exp} and $p2->{exp}" .
-	       $orderby;
-	verify($sql, $ord, $res);
-	for my $p3 (@$a3) {
-	  my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
-	  $sql = "select b, c, d from $table" .
-		 " where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
-		 $orderby;
-	  verify($sql, $ord, $res);
-	}
-      }
-    }
-  }
-  warn "drop table\n";
-  $sql = "drop table $table";
-  $dbh->do($sql) or die $DBI::errstr;
-}
-
-warn "verified $casecnt cases\n";
-warn "done\n";
-
-# vim: set sw=2:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1 branch (mysql-re_ww:3564 to 3565) MySQL Release Engineering6 Jul