List:Commits« Previous MessageNext Message »
From:Staale Smedseng Date:February 27 2009 4:03pm
Subject:bzr commit into mysql-5.1-bugteam branch (staale.smedseng:2824)
View as plain text  
#At file:///Users/staale/z/b29458-51p/ based on revid:staale.smedseng@stripped

 2824 Staale Smedseng	2009-02-27 [merge]
      Commit after merge from 5.1-bugteam

    modified:
      .bzrignore
      mysql-test/lib/mtr_gcov.pl
      mysql-test/mysql-test-run.pl
      mysql-test/r/group_by.result
      mysql-test/r/group_min_max.result
      mysql-test/r/variables.result
      mysql-test/r/view_grant.result
      mysql-test/t/func_group.test
      mysql-test/t/group_by.test
      mysql-test/t/group_min_max.test
      mysql-test/t/ps.test
      mysql-test/t/variables.test
      mysql-test/t/view_grant.test
      sql/opt_range.cc
      sql/protocol.cc
      sql/share/errmsg.txt
      tests/mysql_client_test.c
=== modified file '.bzrignore'
--- a/.bzrignore	2008-12-13 19:42:12 +0000
+++ b/.bzrignore	2009-02-27 11:20:53 +0000
@@ -1295,6 +1295,8 @@ mysql-test/linux_sys_vars.inc
 mysql-test/load_sysvars.inc
 mysql-test/mtr
 mysql-test/mysql-test-run
+mysql-test/mysql-test-gcov.err
+mysql-test/mysql-test-gcov.msg
 mysql-test/mysql-test-run-shell
 mysql-test/mysql-test-run.log
 mysql-test/mysql_test_run_new

=== modified file 'mysql-test/lib/mtr_gcov.pl'
--- a/mysql-test/lib/mtr_gcov.pl	2008-09-05 12:06:22 +0000
+++ b/mysql-test/lib/mtr_gcov.pl	2009-02-27 11:20:53 +0000
@@ -22,40 +22,46 @@ use strict;
 
 sub gcov_prepare ($) {
   my ($dir)= @_;
+  print "Purging gcov information from '$dir'...\n";
 
-  `find $dir -name \*.gcov \
-    -or -name \*.da | xargs rm`;
+  system("find $dir -name \*.gcov -o -name \*.da"
+             . " -o -name \*.gcda | grep -v 'README.gcov\$' | xargs rm");
 }
 
-my @mysqld_src_dirs=
-  (
-   "strings",
-   "mysys",
-   "include",
-   "extra",
-   "regex",
-   "isam",
-   "merge",
-   "myisam",
-   "myisammrg",
-   "heap",
-   "sql",
-  );
-
+#
+# Collect gcov statistics.
+# Arguments:
+#   $dir       basedir, normally source directory
+#   $gcov      gcov utility program [path] name
+#   $gcov_msg  message file name
+#   $gcov_err  error file name
+#
 sub gcov_collect ($$$) {
   my ($dir, $gcov, $gcov_msg, $gcov_err)= @_;
 
+  # Get current directory to return to later.
   my $start_dir= cwd();
 
-  print "Collecting source coverage info...\n";
-  -f $gcov_msg and unlink($gcov_msg);
-  -f $gcov_err and unlink($gcov_err);
-  foreach my $d ( @mysqld_src_dirs )
-  {
-    chdir("$dir/$d");
-    foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) )
-    {
-      `$gcov $f 2>>$gcov_err  >>$gcov_msg`;
+  print "Collecting source coverage info using '$gcov'...\n";
+  -f "$start_dir/$gcov_msg" and unlink("$start_dir/$gcov_msg");
+  -f "$start_dir/$gcov_err" and unlink("$start_dir/$gcov_err");
+
+  my @dirs= `find "$dir" -type d -print | sort`;
+  #print "List of directories:\n@dirs\n";
+
+  foreach my $d ( @dirs ) {
+    my $dir_reported= 0;
+    chomp($d);
+    chdir($d) or next;
+
+    foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) {
+      $f =~ /(.*)\.[ch]c?/;
+      -f "$1.gcno" or next;
+      if (!$dir_reported) {
+	print "Collecting in '$d'...\n";
+	$dir_reported= 1;
+      }
+      system("$gcov $f 2>>$start_dir/$gcov_err >>$start_dir/$gcov_msg");
     }
     chdir($start_dir);
   }

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2009-02-13 15:27:33 +0000
+++ b/mysql-test/mysql-test-run.pl	2009-02-27 11:20:53 +0000
@@ -163,8 +163,9 @@ our $opt_force;
 our $opt_mem= $ENV{'MTR_MEM'};
 
 our $opt_gcov;
-our $opt_gcov_err;
-our $opt_gcov_msg;
+our $opt_gcov_exe= "gcov";
+our $opt_gcov_err= "mysql-test-gcov.msg";
+our $opt_gcov_msg= "mysql-test-gcov.err";
 
 our $glob_debugger= 0;
 our $opt_gdb;
@@ -396,7 +397,7 @@ sub main {
   mtr_print_line();
 
   if ( $opt_gcov ) {
-    gcov_collect($basedir, $opt_gcov,
+    gcov_collect($basedir, $opt_gcov_exe,
 		 $opt_gcov_msg, $opt_gcov_err);
   }
 
@@ -5057,6 +5058,8 @@ Misc options
                         to turn off.
 
   sleep=SECONDS         Passed to mysqltest, will be used as fixed sleep time
+  gcov                  Collect coverage information after the test.
+                        The result is a gcov file per source and header file.
 
 HERE
   exit(1);

=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result	2008-11-12 17:51:47 +0000
+++ b/mysql-test/r/group_by.result	2009-02-26 17:17:06 +0000
@@ -1691,3 +1691,15 @@ FROM t1;
 ERROR 21000: Subquery returns more than 1 row
 DROP TABLE t1;
 SET @@sql_mode = @old_sql_mode;
+SET @old_sql_mode = @@sql_mode;
+SET @@sql_mode='ONLY_FULL_GROUP_BY';
+CREATE TABLE t1(i INT);
+INSERT INTO t1 VALUES (1), (10);
+SELECT COUNT(i) FROM t1;
+COUNT(i)
+2
+SELECT COUNT(i) FROM t1 WHERE i > 1;
+COUNT(i)
+1
+DROP TABLE t1;
+SET @@sql_mode = @old_sql_mode;

=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result	2008-08-28 09:54:50 +0000
+++ b/mysql-test/r/group_min_max.result	2009-02-27 15:07:27 +0000
@@ -2448,3 +2448,18 @@ id	select_type	table	type	possible_keys	
 Warnings:
 Note	1003	select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a`
 drop table t1;
+CREATE TABLE t1 (a int, b int, c int, d int,
+KEY foo (c,d,a,b), KEY bar (c,a,b,d));
+INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4);
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT a,b,c+1,d FROM t1;
+EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	NULL	foo	10	NULL	9	Using where; Using index for group-by
+SELECT DISTINCT c FROM t1 WHERE d=4;
+c
+1
+2
+DROP TABLE t1;
+End of 5.0 tests

=== modified file 'mysql-test/r/variables.result'
--- a/mysql-test/r/variables.result	2009-01-30 13:44:49 +0000
+++ b/mysql-test/r/variables.result	2009-02-27 15:07:27 +0000
@@ -299,59 +299,107 @@ set @@rand_seed1=10000000,@@rand_seed2=1
 select ROUND(RAND(),5);
 ROUND(RAND(),5)
 0.02887
-show variables like '%alloc%';
+
+==+ Testing %alloc% system variables +==
+==+ NOTE:  These values *must* be a multiple of 1024 +==
+==+ Other values will be rounded down to nearest multiple +==
+
+==+ Show initial values +==
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
 Variable_name	Value
 query_alloc_block_size	8192
 query_prealloc_size	8192
 range_alloc_block_size	4096
 transaction_alloc_block_size	8192
 transaction_prealloc_size	4096
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+==+ information_schema data +==
+SELECT * FROM information_schema.session_variables 
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
 VARIABLE_NAME	VARIABLE_VALUE
 QUERY_ALLOC_BLOCK_SIZE	8192
 QUERY_PREALLOC_SIZE	8192
 RANGE_ALLOC_BLOCK_SIZE	4096
 TRANSACTION_ALLOC_BLOCK_SIZE	8192
 TRANSACTION_PREALLOC_SIZE	4096
-set @@range_alloc_block_size=1024*16;
+Testing values that are multiples of 1024
+set @@range_alloc_block_size=1024*15+1024;
+set @@query_alloc_block_size=1024*15+1024*2;
+set @@query_prealloc_size=1024*18-1024;
+set @@transaction_alloc_block_size=1024*21-1024*1;
+set @@transaction_prealloc_size=1024*21-2048;
+==+ Check manipulated values ==+
+select @@query_alloc_block_size;
+@@query_alloc_block_size
+17408
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
+Variable_name	Value
+query_alloc_block_size	17408
+query_prealloc_size	17408
+range_alloc_block_size	16384
+transaction_alloc_block_size	20480
+transaction_prealloc_size	19456
+==+ information_schema data +==
+SELECT * FROM information_schema.session_variables
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
+VARIABLE_NAME	VARIABLE_VALUE
+QUERY_ALLOC_BLOCK_SIZE	17408
+QUERY_PREALLOC_SIZE	17408
+RANGE_ALLOC_BLOCK_SIZE	16384
+TRANSACTION_ALLOC_BLOCK_SIZE	20480
+TRANSACTION_PREALLOC_SIZE	19456
+==+ Manipulate variable values +==
+Testing values that are not 1024 multiples
+set @@range_alloc_block_size=1024*16+1023;
 set @@query_alloc_block_size=1024*17+2;
-set @@query_prealloc_size=1024*18;
+set @@query_prealloc_size=1024*18-1023;
 set @@transaction_alloc_block_size=1024*20-1;
 set @@transaction_prealloc_size=1024*21-1;
 select @@query_alloc_block_size;
 @@query_alloc_block_size
 17408
-show variables like '%alloc%';
+==+ Check manipulated values ==+
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
 Variable_name	Value
 query_alloc_block_size	17408
-query_prealloc_size	18432
+query_prealloc_size	17408
 range_alloc_block_size	16384
 transaction_alloc_block_size	19456
 transaction_prealloc_size	20480
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+==+ information_schema data +==
+SELECT * FROM information_schema.session_variables 
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
 VARIABLE_NAME	VARIABLE_VALUE
 QUERY_ALLOC_BLOCK_SIZE	17408
-QUERY_PREALLOC_SIZE	18432
+QUERY_PREALLOC_SIZE	17408
 RANGE_ALLOC_BLOCK_SIZE	16384
 TRANSACTION_ALLOC_BLOCK_SIZE	19456
 TRANSACTION_PREALLOC_SIZE	20480
+==+ Set values back to the default values +==
 set @@range_alloc_block_size=default;
 set @@query_alloc_block_size=default, @@query_prealloc_size=default;
 set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
-show variables like '%alloc%';
+==+ Check the values now that they are reset +==
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
 Variable_name	Value
 query_alloc_block_size	8192
 query_prealloc_size	8192
 range_alloc_block_size	4096
 transaction_alloc_block_size	8192
 transaction_prealloc_size	4096
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
-VARIABLE_NAME	VARIABLE_VALUE
-QUERY_ALLOC_BLOCK_SIZE	8192
-QUERY_PREALLOC_SIZE	8192
-RANGE_ALLOC_BLOCK_SIZE	4096
-TRANSACTION_ALLOC_BLOCK_SIZE	8192
-TRANSACTION_PREALLOC_SIZE	4096
 SELECT @@version LIKE 'non-existent';
 @@version LIKE 'non-existent'
 0

=== modified file 'mysql-test/r/view_grant.result'
--- a/mysql-test/r/view_grant.result	2009-02-25 12:18:24 +0000
+++ b/mysql-test/r/view_grant.result	2009-02-26 17:20:50 +0000
@@ -921,6 +921,32 @@ c4
 DROP DATABASE mysqltest1;
 DROP DATABASE mysqltest2;
 DROP USER mysqltest_u1@localhost;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE t1(f1 INT, f2 INT);
+CREATE VIEW v1 AS SELECT f1, f2 FROM t1;
+GRANT SELECT (f1) ON t1 TO foo;
+GRANT SELECT (f1) ON v1 TO foo;
+USE db1;
+SELECT f1 FROM t1;
+f1
+SELECT f2 FROM t1;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'f2' in table 't1'
+SELECT * FROM t1;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
+SELECT f1 FROM v1;
+f1
+SELECT f2 FROM v1;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'f2' in table 'v1'
+SELECT * FROM v1;
+ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'v1'
+USE test;
+REVOKE SELECT (f1) ON db1.t1 FROM foo;
+REVOKE SELECT (f1) ON db1.v1 FROM foo;
+DROP USER foo;
+DROP VIEW db1.v1;
+DROP TABLE db1.t1;
+DROP DATABASE db1;
 End of 5.0 tests.
 DROP VIEW IF EXISTS v1;
 DROP TABLE IF EXISTS t1;

=== modified file 'mysql-test/t/func_group.test'
--- a/mysql-test/t/func_group.test	2008-11-24 16:00:09 +0000
+++ b/mysql-test/t/func_group.test	2009-02-26 17:17:06 +0000
@@ -18,6 +18,8 @@ insert into t1 values (3,5,"C");
 insert into t1 values (3,6,"D");
 
 # Test of MySQL field extension with and without matching records.
+#### Note: The two following statements may fail if the execution plan
+#### or optimizer is changed. The result for column c is undefined.
 select a,c,sum(a) from t1 group by a;
 select a,c,sum(a) from t1 where a > 10 group by a;
 select sum(a) from t1 where a > 10;

=== modified file 'mysql-test/t/group_by.test'
--- a/mysql-test/t/group_by.test	2008-11-12 17:51:47 +0000
+++ b/mysql-test/t/group_by.test	2009-02-26 17:17:06 +0000
@@ -1139,4 +1139,22 @@ DROP TABLE t1;
 SET @@sql_mode = @old_sql_mode;
 
 
+#
+# Bug#42567 Invalid GROUP BY error
+#
+
+# Setup of the subtest
+SET @old_sql_mode = @@sql_mode;
+SET @@sql_mode='ONLY_FULL_GROUP_BY';
+
+CREATE TABLE t1(i INT);
+INSERT INTO t1 VALUES (1), (10);
+
+# The actual test
+SELECT COUNT(i) FROM t1;
+SELECT COUNT(i) FROM t1 WHERE i > 1;
+
+# Cleanup of subtest
+DROP TABLE t1;
+SET @@sql_mode = @old_sql_mode;
 

=== modified file 'mysql-test/t/group_min_max.test'
--- a/mysql-test/t/group_min_max.test	2008-08-28 09:54:50 +0000
+++ b/mysql-test/t/group_min_max.test	2009-02-27 15:07:27 +0000
@@ -961,3 +961,25 @@ insert into t1 (a,b) select a, max(b)+1 
 select * from t1;
 explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a;
 drop table t1;
+
+
+#
+# Bug #41610: key_infix_len can be overwritten causing some group by queries
+# to return no rows
+#
+
+CREATE TABLE t1 (a int, b int, c int, d int,
+  KEY foo (c,d,a,b), KEY bar (c,a,b,d));
+
+INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4);
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT * FROM t1;
+INSERT INTO t1 SELECT a,b,c+1,d FROM t1;
+
+#Should be non-empty
+EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
+SELECT DISTINCT c FROM t1 WHERE d=4;
+
+DROP TABLE t1;
+
+--echo End of 5.0 tests

=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test	2009-02-25 11:47:28 +0000
+++ b/mysql-test/t/ps.test	2009-02-25 15:53:49 +0000
@@ -946,8 +946,13 @@ set global max_prepared_stmt_count=3;
 select @@max_prepared_stmt_count;
 show status like 'prepared_stmt_count';
 prepare stmt from "select 1";
+
 connect (con1,localhost,root,,);
+
+# Switch to connection con1
 connection con1;
+let $con1_id=`SELECT CONNECTION_ID()`;
+
 prepare stmt from "select 2";
 prepare stmt1 from "select 3";
 --error ER_MAX_PREPARED_STMT_COUNT_REACHED
@@ -957,18 +962,17 @@ connection default;
 prepare stmt2 from "select 4";
 select @@max_prepared_stmt_count;
 show status like 'prepared_stmt_count';
+
+# Disconnect connection con1 and switch to default connection
 disconnect con1;
 connection default;
-# Wait for the connection to die: deal with a possible race
+
+# Wait for the connection con1 to die
+let $wait_condition=SELECT COUNT(*)=0 FROM information_schema.processlist WHERE id=$con1_id;
+--source include/wait_condition.inc
+
 deallocate prepare stmt;
-let $query= select variable_value from information_schema.global_status
-            where variable_name = 'prepared_stmt_count';
-let $count= `$query`;
-if ($count)
-{
---sleep 1
-  let $count= `$query`;
-}
+
 select @@max_prepared_stmt_count;
 show status like 'prepared_stmt_count';
 #

=== modified file 'mysql-test/t/variables.test'
--- a/mysql-test/t/variables.test	2009-02-02 22:56:45 +0000
+++ b/mysql-test/t/variables.test	2009-02-27 08:24:57 +0000
@@ -173,21 +173,63 @@ select @@timestamp>0;
 set @@rand_seed1=10000000,@@rand_seed2=1000000;
 select ROUND(RAND(),5);
 
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
-set @@range_alloc_block_size=1024*16;
+
+--echo
+--echo ==+ Testing %alloc% system variables +==
+--echo ==+ NOTE:  These values *must* be a multiple of 1024 +==
+--echo ==+ Other values will be rounded down to nearest multiple +==
+--echo
+--echo ==+ Show initial values +==
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
+
+--echo ==+ information_schema data +==
+SELECT * FROM information_schema.session_variables 
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
+--echo Testing values that are multiples of 1024
+set @@range_alloc_block_size=1024*15+1024;
+set @@query_alloc_block_size=1024*15+1024*2;
+set @@query_prealloc_size=1024*18-1024;
+set @@transaction_alloc_block_size=1024*21-1024*1;
+set @@transaction_prealloc_size=1024*21-2048;
+--echo ==+ Check manipulated values ==+
+select @@query_alloc_block_size;
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
+--echo ==+ information_schema data +==
+SELECT * FROM information_schema.session_variables
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
+--echo ==+ Manipulate variable values +==
+--echo Testing values that are not 1024 multiples
+set @@range_alloc_block_size=1024*16+1023;
 set @@query_alloc_block_size=1024*17+2;
-set @@query_prealloc_size=1024*18;
+set @@query_prealloc_size=1024*18-1023;
 set @@transaction_alloc_block_size=1024*20-1;
 set @@transaction_prealloc_size=1024*21-1;
 select @@query_alloc_block_size;
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+--echo ==+ Check manipulated values ==+
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
+--echo ==+ information_schema data +==
+SELECT * FROM information_schema.session_variables 
+WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1;
+--echo ==+ Set values back to the default values +==
 set @@range_alloc_block_size=default;
 set @@query_alloc_block_size=default, @@query_prealloc_size=default;
 set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+--echo ==+ Check the values now that they are reset +==
+SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size',
+'query_alloc_block_size', 'query_prealloc_size',
+'transaction_alloc_block_size', 'transaction_prealloc_size');
 
 #
 # Bug #10904 Illegal mix of collations between

=== modified file 'mysql-test/t/view_grant.test'
--- a/mysql-test/t/view_grant.test	2009-02-25 10:19:29 +0000
+++ b/mysql-test/t/view_grant.test	2009-02-26 17:20:50 +0000
@@ -1191,6 +1191,46 @@ DROP DATABASE mysqltest1;
 DROP DATABASE mysqltest2;
 DROP USER mysqltest_u1@localhost;
 
+
+#
+# Bug #41354: Access control is bypassed when all columns of a view are 
+# selected by * wildcard
+
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE t1(f1 INT, f2 INT);
+CREATE VIEW v1 AS SELECT f1, f2 FROM t1;
+
+GRANT SELECT (f1) ON t1 TO foo;
+GRANT SELECT (f1) ON v1 TO foo;
+
+connect (addconfoo, localhost, foo,,);
+connection addconfoo;
+USE db1;
+
+
+SELECT f1 FROM t1;
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT f2 FROM t1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT * FROM t1;
+
+SELECT f1 FROM v1;
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT f2 FROM v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT * FROM v1;
+
+connection default;
+USE test;
+disconnect addconfoo;
+REVOKE SELECT (f1) ON db1.t1 FROM foo;
+REVOKE SELECT (f1) ON db1.v1 FROM foo;
+DROP USER foo;
+DROP VIEW db1.v1;
+DROP TABLE db1.t1;
+DROP DATABASE db1;
+
 --echo End of 5.0 tests.
 
 

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2009-01-05 16:10:20 +0000
+++ b/sql/opt_range.cc	2009-02-27 15:07:27 +0000
@@ -9239,32 +9239,37 @@ get_best_group_min_max(PARAM *param, SEL
   */
   KEY *cur_index_info= table->key_info;
   KEY *cur_index_info_end= cur_index_info + table->s->keys;
-  KEY_PART_INFO *cur_part= NULL;
-  KEY_PART_INFO *end_part; /* Last part for loops. */
-  /* Last index part. */
-  KEY_PART_INFO *last_part= NULL;
-  KEY_PART_INFO *first_non_group_part= NULL;
-  KEY_PART_INFO *first_non_infix_part= NULL;
-  uint key_infix_parts= 0;
-  uint cur_group_key_parts= 0;
-  uint cur_group_prefix_len= 0;
   /* Cost-related variables for the best index so far. */
   double best_read_cost= DBL_MAX;
   ha_rows best_records= 0;
   SEL_ARG *best_index_tree= NULL;
   ha_rows best_quick_prefix_records= 0;
   uint best_param_idx= 0;
-  double cur_read_cost= DBL_MAX;
-  ha_rows cur_records;
+
+  const uint pk= param->table->s->primary_key;
   SEL_ARG *cur_index_tree= NULL;
   ha_rows cur_quick_prefix_records= 0;
   uint cur_param_idx=MAX_KEY;
-  key_map cur_used_key_parts;
-  uint pk= param->table->s->primary_key;
 
   for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
        cur_index_info++, cur_index++)
   {
+    KEY_PART_INFO *cur_part;
+    KEY_PART_INFO *end_part; /* Last part for loops. */
+    /* Last index part. */
+    KEY_PART_INFO *last_part;
+    KEY_PART_INFO *first_non_group_part;
+    KEY_PART_INFO *first_non_infix_part;
+    uint key_infix_parts;
+    uint cur_group_key_parts= 0;
+    uint cur_group_prefix_len= 0;
+    double cur_read_cost;
+    ha_rows cur_records;
+    key_map used_key_parts_map;
+    uint cur_key_infix_len= 0;
+    uchar cur_key_infix[MAX_KEY_LENGTH];
+    uint cur_used_key_parts;
+    
     /* Check (B1) - if current index is covering. */
     if (!table->covering_keys.is_set(cur_index))
       goto next_index;
@@ -9334,7 +9339,7 @@ get_best_group_min_max(PARAM *param, SEL
     else if (join->select_distinct)
     {
       select_items_it.rewind();
-      cur_used_key_parts.clear_all();
+      used_key_parts_map.clear_all();
       uint max_key_part= 0;
       while ((item= select_items_it++))
       {
@@ -9345,13 +9350,13 @@ get_best_group_min_max(PARAM *param, SEL
           Check if this attribute was already present in the select list.
           If it was present, then its corresponding key part was alredy used.
         */
-        if (cur_used_key_parts.is_set(key_part_nr))
+        if (used_key_parts_map.is_set(key_part_nr))
           continue;
         if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
           goto next_index;
         cur_part= cur_index_info->key_part + key_part_nr - 1;
         cur_group_prefix_len+= cur_part->store_length;
-        cur_used_key_parts.set_bit(key_part_nr);
+        used_key_parts_map.set_bit(key_part_nr);
         ++cur_group_key_parts;
         max_key_part= max(max_key_part,key_part_nr);
       }
@@ -9363,7 +9368,7 @@ get_best_group_min_max(PARAM *param, SEL
       */
       ulonglong all_parts, cur_parts;
       all_parts= (1<<max_key_part) - 1;
-      cur_parts= cur_used_key_parts.to_ulonglong() >> 1;
+      cur_parts= used_key_parts_map.to_ulonglong() >> 1;
       if (all_parts != cur_parts)
         goto next_index;
     }
@@ -9413,7 +9418,8 @@ get_best_group_min_max(PARAM *param, SEL
                                                         &dummy);
         if (!get_constant_key_infix(cur_index_info, index_range_tree,
                                     first_non_group_part, min_max_arg_part,
-                                    last_part, thd, key_infix, &key_infix_len,
+                                    last_part, thd, cur_key_infix, 
+                                    &cur_key_infix_len,
                                     &first_non_infix_part))
           goto next_index;
       }
@@ -9467,9 +9473,9 @@ get_best_group_min_max(PARAM *param, SEL
     }
 
     /* If we got to this point, cur_index_info passes the test. */
-    key_infix_parts= key_infix_len ?
+    key_infix_parts= cur_key_infix_len ?
                      (first_non_infix_part - first_non_group_part) : 0;
-    used_key_parts= cur_group_key_parts + key_infix_parts;
+    cur_used_key_parts= cur_group_key_parts + key_infix_parts;
 
     /* Compute the cost of using this index. */
     if (tree)
@@ -9481,7 +9487,7 @@ get_best_group_min_max(PARAM *param, SEL
       cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
                                                     cur_index_tree, TRUE);
     }
-    cost_group_min_max(table, cur_index_info, used_key_parts,
+    cost_group_min_max(table, cur_index_info, cur_used_key_parts,
                        cur_group_key_parts, tree, cur_index_tree,
                        cur_quick_prefix_records, have_min, have_max,
                        &cur_read_cost, &cur_records);
@@ -9492,7 +9498,6 @@ get_best_group_min_max(PARAM *param, SEL
     */
     if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
     {
-      DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY);
       index_info= cur_index_info;
       index= cur_index;
       best_read_cost= cur_read_cost;
@@ -9502,11 +9507,13 @@ get_best_group_min_max(PARAM *param, SEL
       best_param_idx= cur_param_idx;
       group_key_parts= cur_group_key_parts;
       group_prefix_len= cur_group_prefix_len;
+      key_infix_len= cur_key_infix_len;
+      if (key_infix_len)
+        memcpy (key_infix, cur_key_infix, sizeof (key_infix));
+      used_key_parts= cur_used_key_parts;
     }
 
-  next_index:
-    cur_group_key_parts= 0;
-    cur_group_prefix_len= 0;
+  next_index:;
   }
   if (!index_info) /* No usable index found. */
     DBUG_RETURN(NULL);

=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc	2008-08-11 18:02:03 +0000
+++ b/sql/protocol.cc	2009-02-27 08:03:47 +0000
@@ -573,7 +573,8 @@ bool Protocol::send_fields(List<Item> *l
       else
       {
         /* With conversion */
-        uint max_char_len;
+        ulonglong max_length;
+        uint32 field_length;
         int2store(pos, thd_charset->number);
         /*
           For TEXT/BLOB columns, field_length describes the maximum data
@@ -584,12 +585,22 @@ bool Protocol::send_fields(List<Item> *l
           char_count * mbmaxlen, where character count is taken from the
           definition of the column. In other words, the maximum number
           of characters here is limited by the column definition.
+
+          When one has a LONG TEXT column with a single-byte
+          character set, and the connection character set is multi-byte, the
+          client may get fields longer than UINT_MAX32, due to
+          <character set column> -> <character set connection> conversion.
+          In that case column max length does not fit into the 4 bytes
+          reserved for it in the protocol.
         */
-        max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
-                      field.type <= (int) MYSQL_TYPE_BLOB) ?
-                      field.length / item->collation.collation->mbminlen :
-                      field.length / item->collation.collation->mbmaxlen;
-        int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
+        max_length= (field.type >= MYSQL_TYPE_TINY_BLOB &&
+                     field.type <= MYSQL_TYPE_BLOB) ?
+                     field.length / item->collation.collation->mbminlen :
+                     field.length / item->collation.collation->mbmaxlen;
+        max_length*= thd_charset->mbmaxlen;
+        field_length= (max_length > UINT_MAX32) ? 
+          UINT_MAX32 : (uint32) max_length;
+        int4store(pos + 2, field_length);
       }
       pos[6]= field.type;
       int2store(pos+7,field.flags);

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2009-02-18 20:10:19 +0000
+++ b/sql/share/errmsg.txt	2009-02-26 14:01:57 +0000
@@ -6154,3 +6154,18 @@ WARN_PLUGIN_BUSY
 
 ER_VARIABLE_IS_READONLY
   eng "%s variable '%s' is read-only. Use SET %s to assign the value"
+
+ER_WARN_ENGINE_TRANSACTION_ROLLBACK
+  eng "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted"
+
+ER_SLAVE_HEARTBEAT_FAILURE
+  eng "Unexpected master's heartbeat data: %s"
+ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+  eng "The requested value for the heartbeat period %s %s"
+
+ER_NDB_REPLICATION_SCHEMA_ERROR
+        eng "Bad schema for mysql.ndb_replication table. Message: %-.64s"
+ER_CONFLICT_FN_PARSE_ERROR
+        eng "Error in parsing conflict function. Message: %-.64s"
+ER_EXCEPTIONS_WRITE_ERROR
+        eng "Write to exceptions table failed. Message: %-.128s""

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2009-02-19 08:56:16 +0000
+++ b/tests/mysql_client_test.c	2009-02-26 12:14:33 +0000
@@ -723,6 +723,7 @@ static void do_verify_prepare_field(MYSQ
 {
   MYSQL_FIELD *field;
   CHARSET_INFO *cs;
+  ulonglong expected_field_length;
 
   if (!(field= mysql_fetch_field_direct(result, no)))
   {
@@ -731,6 +732,8 @@ static void do_verify_prepare_field(MYSQ
   }
   cs= get_charset(field->charsetnr, 0);
   DIE_UNLESS(cs);
+  if ((expected_field_length= length * cs->mbmaxlen) > UINT_MAX32)
+    expected_field_length= UINT_MAX32;
   if (!opt_silent)
   {
     fprintf(stdout, "\n field[%d]:", no);
@@ -745,8 +748,8 @@ static void do_verify_prepare_field(MYSQ
       fprintf(stdout, "\n    org_table:`%s`\t(expected: `%s`)",
               field->org_table, org_table);
     fprintf(stdout, "\n    database :`%s`\t(expected: `%s`)", field->db, db);
-    fprintf(stdout, "\n    length   :`%lu`\t(expected: `%lu`)",
-            field->length, length * cs->mbmaxlen);
+    fprintf(stdout, "\n    length   :`%lu`\t(expected: `%llu`)",
+            field->length, expected_field_length);
     fprintf(stdout, "\n    maxlength:`%ld`", field->max_length);
     fprintf(stdout, "\n    charsetnr:`%d`", field->charsetnr);
     fprintf(stdout, "\n    default  :`%s`\t(expected: `%s`)",
@@ -782,11 +785,11 @@ static void do_verify_prepare_field(MYSQ
     as utf8. Field length is calculated as number of characters * maximum
     number of bytes a character can occupy.
   */
-  if (length && field->length != length * cs->mbmaxlen)
+  if (length && (field->length != expected_field_length))
   {
-    fprintf(stderr, "Expected field length: %d,  got length: %d\n",
-            (int) (length * cs->mbmaxlen), (int) field->length);
-    DIE_UNLESS(field->length == length * cs->mbmaxlen);
+    fprintf(stderr, "Expected field length: %llu,  got length: %lu\n",
+            expected_field_length, field->length);
+    DIE_UNLESS(field->length == expected_field_length);
   }
   if (def)
     DIE_UNLESS(strcmp(field->def, def) == 0);


Attachment: [text/bzr-bundle] bzr/staale.smedseng@sun.com-20090227160332-3k1kc0rao6y07cbp.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (staale.smedseng:2824) Staale Smedseng27 Feb