#At file:///home/bzr/merges/merge-6.0-rpl/
2703 Mats Kindahl 2008-10-09 [merge]
Merge 5.1-rpl into 6.0-rpl.
added:
mysql-test/suite/binlog/r/binlog_grant.result
mysql-test/suite/binlog/t/binlog_grant.test
mysql-test/suite/rpl/r/rpl_binlog_query_filter_rules.result
mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules-master.opt
mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules.test
modified:
mysql-test/extra/rpl_tests/rpl_log.test
mysql-test/extra/rpl_tests/rpl_row_basic.test
mysql-test/include/grant_cache.inc
mysql-test/lib/My/Platform.pm
mysql-test/lib/My/SafeProcess.pm
mysql-test/lib/My/SysInfo.pm
mysql-test/mysql-test-run.pl
mysql-test/r/create.result
mysql-test/r/default.result
mysql-test/r/func_regexp.result
mysql-test/r/grant2.result
mysql-test/r/grant_cache_no_prot.result
mysql-test/r/grant_cache_ps_prot.result
mysql-test/r/status.result
mysql-test/r/type_datetime.result
mysql-test/r/type_set.result
mysql-test/r/view_grant.result
mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
mysql-test/suite/rpl/t/rpl_ps.test
mysql-test/suite/rpl_ndb_big/r/rpl_ndb_log.result
mysql-test/suite/rpl_ndb_big/r/rpl_row_basic_7ndb.result
mysql-test/t/create.test
mysql-test/t/default.test
mysql-test/t/func_regexp.test
mysql-test/t/grant2.test
mysql-test/t/status.test
mysql-test/t/type_datetime.test
mysql-test/t/type_set.test
mysql-test/t/view_grant.test
sql/handler.cc
sql/item.cc
sql/item_cmpfunc.cc
sql/item_cmpfunc.h
sql/log.cc
sql/log.h
sql/log_event.cc
sql/set_var.cc
sql/set_var.h
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_cache.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_derived.cc
sql/sql_insert.cc
sql/sql_parse.cc
sql/table.cc
sql/table.h
=== modified file 'mysql-test/extra/rpl_tests/rpl_log.test'
--- a/mysql-test/extra/rpl_tests/rpl_log.test 2008-10-07 10:26:19 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_log.test 2008-10-09 08:39:43 +0000
@@ -68,10 +68,7 @@ eval create table t3 (a int)ENGINE=$engi
connection master;
select * from t1 order by 1 asc;
-save_master_pos;
-connection slave;
-
-sync_with_master;
+sync_slave_with_master;
#check t1 on slave to ensure whether it's identical with on master
select * from t1 order by 1 asc;
flush logs;
@@ -91,6 +88,7 @@ source include/show_binlog_events.inc;
show binlog events in 'master-bin.000002';
show binary logs;
sync_slave_with_master;
+--source include/wait_for_slave_to_start.inc
show binary logs;
--replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION
--replace_column 2 # 5 #
=== modified file 'mysql-test/extra/rpl_tests/rpl_row_basic.test'
--- a/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-09-06 07:22:50 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-10-09 08:39:43 +0000
@@ -451,3 +451,23 @@ connection master;
drop table t1, t2, t3, t4, t5, t6, t7;
sync_slave_with_master;
+#
+# BUG#32709: Assertion failed: trx_data->empty(), file .\log.cc, line 1293
+#
+
+connection master;
+eval CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=$type;
+
+INSERT INTO t1 VALUES (1), (2), (3);
+--error ER_DUP_ENTRY
+UPDATE t1 SET a = 10;
+INSERT INTO t1 VALUES (4);
+sync_slave_with_master;
+
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+connection master;
+drop table t1;
+sync_slave_with_master;
=== modified file 'mysql-test/include/grant_cache.inc'
--- a/mysql-test/include/grant_cache.inc 2007-05-24 20:13:49 +0000
+++ b/mysql-test/include/grant_cache.inc 2008-09-03 14:45:40 +0000
@@ -136,7 +136,7 @@ connect (user3,localhost,mysqltest_3,,my
connection user3;
select "user3";
--replace_result 127.0.0.1 localhost
---error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_TABLEACCESS_DENIED_ERROR
select * from t1;
select a from t1;
--replace_result 127.0.0.1 localhost
=== modified file 'mysql-test/lib/My/Platform.pm'
--- a/mysql-test/lib/My/Platform.pm 2008-10-08 20:31:21 +0000
+++ b/mysql-test/lib/My/Platform.pm 2008-10-09 08:39:43 +0000
@@ -64,19 +64,25 @@ BEGIN {
# in cygwin perl (that uses unix paths)
#
+use Memoize;
+if (!IS_WIN32PERL){
+ memoize('mixed_path');
+ memoize('native_path');
+ memoize('posix_path');
+}
+
sub mixed_path {
my ($path)= @_;
if (IS_CYGWIN){
return unless defined $path;
my $cmd= "cygpath -m $path";
- print "$cmd\n";
- $path= `$cmd`;
+ $path= `$cmd` or
+ print "Failed to run: '$cmd', $!\n";
chomp $path;
}
return $path;
}
-
sub native_path {
my ($path)= @_;
$path=~ s/\//\\/g
@@ -84,7 +90,6 @@ sub native_path {
return $path;
}
-
sub posix_path {
my ($path)= @_;
if (IS_CYGWIN){
=== modified file 'mysql-test/lib/My/SafeProcess.pm'
--- a/mysql-test/lib/My/SafeProcess.pm 2008-10-08 20:06:10 +0000
+++ b/mysql-test/lib/My/SafeProcess.pm 2008-10-08 20:30:56 +0000
@@ -214,6 +214,14 @@ sub timer {
};
$0= "safe_timer($duration)";
+
+ if (IS_WIN32PERL){
+ # Just a thread in same process
+ sleep($duration);
+ print STDERR "timer $$: expired after $duration seconds\n";
+ exit(0);
+ }
+
my $count_down= $duration;
while($count_down--){
=== modified file 'mysql-test/lib/My/SysInfo.pm'
--- a/mysql-test/lib/My/SysInfo.pm 2008-07-24 20:22:47 +0000
+++ b/mysql-test/lib/My/SysInfo.pm 2008-10-08 18:25:28 +0000
@@ -76,7 +76,7 @@ sub _kstat {
my ($self)= @_;
while (1){
my $instance_num= $self->{cpus} ? @{$self->{cpus}} : 0;
- my $list= `kstat -p -m cpu_info -i $instance_num`;
+ my $list= `kstat -p -m cpu_info -i $instance_num 2> /dev/null`;
my @lines= split('\n', $list) or last; # Break loop
my $cpuinfo= {};
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2008-10-08 20:31:21 +0000
+++ b/mysql-test/mysql-test-run.pl 2008-10-09 08:39:43 +0000
@@ -353,7 +353,7 @@ sub main {
if ($opt_force){
# All test should have been run, print any that are still in $tests
foreach my $test ( @$tests ){
- $test->print_test();
+ $test->print_test();
}
}
@@ -544,15 +544,20 @@ sub run_test_server ($$$) {
my $next;
my $second_best;
- for(my $i= 0; $i <= $#$tests; $i++)
+ for(my $i= 0; $i <= @$tests; $i++)
{
my $t= $tests->[$i];
+ last unless defined $t;
+
if (run_testcase_check_skip_test($t)){
# Move the test to completed list
#mtr_report("skip - Moving test $i to completed");
push(@$completed, splice(@$tests, $i, 1));
- next;
+
+ # Since the test at pos $i was taken away, next
+ # test will also be at $i -> redo
+ redo;
}
# Limit number of parallell NDB tests
@@ -582,7 +587,7 @@ sub run_test_server ($$$) {
# Use second best choice if no other test has been found
if (!$next and defined $second_best){
#mtr_report("Take second best choice $second_best");
- mtr_error("Internal error, second best too large")
+ mtr_error("Internal error, second best too large($second_best)")
if $second_best > $#$tests;
$next= splice(@$tests, $second_best, 1);
}
=== modified file 'mysql-test/r/create.result'
--- a/mysql-test/r/create.result 2008-08-04 14:30:50 +0000
+++ b/mysql-test/r/create.result 2008-10-09 08:39:43 +0000
@@ -1564,6 +1564,17 @@ SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_Comment
t1 1 c1 1 c1 A NULL NULL NULL YES BTREE
DROP TABLE t1;
+CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL);
+INSERT IGNORE INTO t1 (b) VALUES (5);
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+SELECT a FROM t1;
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+SELECT a FROM t1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+SELECT a FROM t1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+DROP TABLE t1, t2;
End of 5.0 tests
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
=== modified file 'mysql-test/r/default.result'
--- a/mysql-test/r/default.result 2007-09-20 09:10:05 +0000
+++ b/mysql-test/r/default.result 2008-09-03 08:06:03 +0000
@@ -205,4 +205,19 @@ Warnings:
Warning 1364 Field 'id' doesn't have a default value
drop view v1;
drop table t1;
+create table t1 (a int unique);
+create table t2 (b int default 10);
+insert into t1 (a) values (1);
+insert into t2 (b) values (1);
+insert into t1 (a) select b from t2 on duplicate key update a=default;
+select * from t1;
+a
+NULL
+insert into t1 (a) values (1);
+insert into t1 (a) select b from t2 on duplicate key update a=default(b);
+select * from t1;
+a
+NULL
+10
+drop table t1, t2;
End of 5.0 tests.
=== modified file 'mysql-test/r/func_regexp.result'
--- a/mysql-test/r/func_regexp.result 2008-08-15 05:53:25 +0000
+++ b/mysql-test/r/func_regexp.result 2008-09-05 08:36:02 +0000
@@ -114,6 +114,18 @@ End of 4.1 tests
SELECT 1 REGEXP NULL;
1 REGEXP NULL
NULL
+SELECT '' REGEXP BINARY NULL;
+'' REGEXP BINARY NULL
+NULL
+SELECT NULL REGEXP BINARY NULL;
+NULL REGEXP BINARY NULL
+NULL
+SELECT 'A' REGEXP BINARY NULL;
+'A' REGEXP BINARY NULL
+NULL
+SELECT "ABC" REGEXP BINARY NULL;
+"ABC" REGEXP BINARY NULL
+NULL
End of 5.0 tests
CREATE TABLE t1(a INT, b CHAR(4));
INSERT INTO t1 VALUES (1, '6.1'), (1, '7.0'), (1, '8.0');
=== modified file 'mysql-test/r/grant2.result'
--- a/mysql-test/r/grant2.result 2008-08-04 14:30:50 +0000
+++ b/mysql-test/r/grant2.result 2008-10-09 08:39:43 +0000
@@ -435,7 +435,7 @@ USE db1;
SELECT c FROM t2;
ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in
table 't2'
SELECT * FROM t2;
-ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in
table 't2'
+ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for table 't2'
SELECT * FROM t1 JOIN t2 USING (b);
ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in
table 't2'
DROP TABLE db1.t1, db1.t2;
=== modified file 'mysql-test/r/grant_cache_no_prot.result'
--- a/mysql-test/r/grant_cache_no_prot.result 2007-05-24 20:13:49 +0000
+++ b/mysql-test/r/grant_cache_no_prot.result 2008-09-03 14:45:40 +0000
@@ -155,7 +155,7 @@ select "user3";
user3
user3
select * from t1;
-ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in
table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
select a from t1;
a
1
=== modified file 'mysql-test/r/grant_cache_ps_prot.result'
--- a/mysql-test/r/grant_cache_ps_prot.result 2007-05-24 20:13:49 +0000
+++ b/mysql-test/r/grant_cache_ps_prot.result 2008-09-03 14:45:40 +0000
@@ -155,7 +155,7 @@ select "user3";
user3
user3
select * from t1;
-ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in
table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
select a from t1;
a
1
=== modified file 'mysql-test/r/status.result'
--- a/mysql-test/r/status.result 2008-05-29 12:56:51 +0000
+++ b/mysql-test/r/status.result 2008-10-09 08:39:43 +0000
@@ -180,6 +180,24 @@ Variable_name Value
Com_alter_function 0
Com_create_function 1
Com_drop_function 1
+create database db37908;
+create table db37908.t1(f1 int);
+insert into db37908.t1 values(1);
+grant usage,execute on test.* to mysqltest_1@localhost;
+create procedure proc37908() begin select 1; end |
+create function func37908() returns int sql security invoker
+return (select * from db37908.t1 limit 1)|
+select * from db37908.t1;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show function status where name ='func37908' and 1 in (select func37908());
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+drop database db37908;
+drop procedure proc37908;
+drop function func37908;
DROP VIEW IF EXISTS v1;
CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS
VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected';
=== modified file 'mysql-test/r/type_datetime.result'
--- a/mysql-test/r/type_datetime.result 2007-12-10 16:24:46 +0000
+++ b/mysql-test/r/type_datetime.result 2008-10-09 08:39:43 +0000
@@ -562,6 +562,29 @@ where id in (select id from t2 as x1 whe
id cur_date
set @@optimizer_switch='';
drop table t1,t2;
+SELECT
+CAST('NULL' AS DATE) <=> CAST('2008-01-01' AS DATE) n1,
+CAST('2008-01-01' AS DATE) <=> CAST('NULL' AS DATE) n2,
+CAST('NULL' AS DATE) <=> CAST('NULL' AS DATE) n3,
+CAST('NULL' AS DATE) <> CAST('2008-01-01' AS DATE) n4,
+CAST('2008-01-01' AS DATE) <> CAST('NULL' AS DATE) n5,
+CAST('NULL' AS DATE) <> CAST('NULL' AS DATE) n6,
+CAST('NULL' AS DATE) < CAST('2008-01-01' AS DATE) n7,
+CAST('2008-01-01' AS DATE) < CAST('NULL' AS DATE) n8,
+CAST('NULL' AS DATE) < CAST('NULL' AS DATE) n9;
+n1 n2 n3 n4 n5 n6 n7 n8 n9
+0 0 1 NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
+Warning 1292 Incorrect datetime value: 'NULL'
End of 5.0 tests
set @org_mode=@@sql_mode;
create table t1 (da date default '1962-03-03 23:33:34', dt datetime default
'1962-03-03');
=== modified file 'mysql-test/r/type_set.result'
--- a/mysql-test/r/type_set.result 2008-03-14 20:40:21 +0000
+++ b/mysql-test/r/type_set.result 2008-09-05 15:21:59 +0000
@@ -93,4 +93,14 @@ c
1,2,3
64
DROP TABLE t1;
+CREATE TABLE t1 (
+set_unique_utf8 set ('a','b','c','d','e','f','g','h','i','j','k','l',
+'m','n','o','p','q','r','s','t','u','v','w','x',
+'y','z') CHARACTER SET utf8,
+unique (set_unique_utf8)
+);
+INSERT INTO t1 ( set_unique_utf8 ) VALUES ( '' );
+INSERT INTO t1 ( set_unique_utf8 ) VALUES ( '' );
+ERROR 23000: Duplicate entry '' for key 'set_unique_utf8'
+DROP TABLE t1;
End of 5.0 tests
=== modified file 'mysql-test/r/view_grant.result'
--- a/mysql-test/r/view_grant.result 2008-06-26 18:56:36 +0000
+++ b/mysql-test/r/view_grant.result 2008-10-09 08:39:43 +0000
@@ -969,3 +969,42 @@ DROP DATABASE mysqltest1;
DROP USER mysqluser1@localhost;
USE test;
End of 5.1 tests.
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+CREATE TABLE t1 ( a INT, b INT );
+CREATE TABLE t2 ( a INT, b INT );
+CREATE VIEW v1 AS SELECT a, b FROM t1;
+GRANT SELECT( a ) ON v1 TO mysqluser1@localhost;
+GRANT UPDATE( b ) ON t2 TO mysqluser1@localhost;
+SELECT * FROM mysqltest1.v1;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1'
+CREATE VIEW v1 AS SELECT * FROM mysqltest1.t2;
+ERROR 42000: ANY command denied to user 'mysqluser1'@'localhost' for table 't2'
+DROP TABLE t1, t2;
+DROP VIEW v1;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+CREATE VIEW v1 AS SELECT * FROM information_schema.tables LIMIT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 1 AS A;
+CREATE VIEW test.v3 AS SELECT 1 AS a;
+GRANT SELECT ON mysqltest1.* to mysqluser1@localhost;
+GRANT ALL ON test.* TO mysqluser1@localhost;
+PREPARE stmt_v1 FROM "SELECT * FROM mysqltest1.v1";
+PREPARE stmt_v2 FROM "SELECT * FROM mysqltest1.v2";
+REVOKE SELECT ON mysqltest1.* FROM mysqluser1@localhost;
+EXECUTE stmt_v1;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1'
+EXECUTE stmt_v2;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v2'
+PREPARE stmt FROM "SELECT a FROM v3";
+EXECUTE stmt;
+a
+1
+DROP VIEW v1, v2;
+DROP DATABASE mysqltest1;
+DROP VIEW test.v3;
+DROP USER mysqluser1@localhost;
=== added file 'mysql-test/suite/binlog/r/binlog_grant.result'
--- a/mysql-test/suite/binlog/r/binlog_grant.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/r/binlog_grant.result 2008-09-09 10:19:31 +0000
@@ -0,0 +1,28 @@
+reset master;
+set @saved_binlog_format = @@global.binlog_format;
+create user mysqltest_1@localhost;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+**** Variable SQL_LOG_BIN ****
+[root]
+set global sql_log_bin = 1;
+ERROR HY000: Variable 'sql_log_bin' is a SESSION variable and can't be used with SET
GLOBAL
+set session sql_log_bin = 1;
+[plain]
+set global sql_log_bin = 1;
+ERROR HY000: Variable 'sql_log_bin' is a SESSION variable and can't be used with SET
GLOBAL
+set session sql_log_bin = 1;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+**** Variable BINLOG_FORMAT ****
+[root]
+set global binlog_format = row;
+set session binlog_format = row;
+[plain]
+set global binlog_format = row;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+set session binlog_format = row;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+**** Clean up ****
+set global binlog_format = @saved_binlog_format;
+drop user mysqltest_1@localhost;
=== added file 'mysql-test/suite/binlog/t/binlog_grant.test'
--- a/mysql-test/suite/binlog/t/binlog_grant.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_grant.test 2008-09-09 10:19:31 +0000
@@ -0,0 +1,60 @@
+# Test grants for various objects (especially variables) related to
+# the binary log
+
+source include/have_log_bin.inc;
+
+connection default;
+--disable_warnings
+reset master;
+--enable_warnings
+
+set @saved_binlog_format = @@global.binlog_format;
+create user mysqltest_1@localhost;
+show grants for mysqltest_1@localhost;
+
+connect (plain,localhost,mysqltest_1,,test);
+connect (root,localhost,root,,test);
+
+# Testing setting both session and global SQL_LOG_BIN variable both as
+# root and as plain user.
+
+--echo **** Variable SQL_LOG_BIN ****
+
+connection root;
+--echo [root]
+--error ER_LOCAL_VARIABLE
+set global sql_log_bin = 1;
+set session sql_log_bin = 1;
+
+connection plain;
+--echo [plain]
+--error ER_LOCAL_VARIABLE
+set global sql_log_bin = 1;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set session sql_log_bin = 1;
+
+
+# Testing setting both session and global BINLOG_FORMAT variable both
+# as root and as plain user.
+
+--echo **** Variable BINLOG_FORMAT ****
+
+connection root;
+--echo [root]
+set global binlog_format = row;
+set session binlog_format = row;
+
+connection plain;
+--echo [plain]
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set global binlog_format = row;
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+set session binlog_format = row;
+
+--echo **** Clean up ****
+disconnect plain;
+disconnect root;
+
+connection default;
+set global binlog_format = @saved_binlog_format;
+drop user mysqltest_1@localhost;
=== added file 'mysql-test/suite/rpl/r/rpl_binlog_query_filter_rules.result'
--- a/mysql-test/suite/rpl/r/rpl_binlog_query_filter_rules.result 1970-01-01 00:00:00
+0000
+++ b/mysql-test/suite/rpl/r/rpl_binlog_query_filter_rules.result 2008-09-03 10:01:18
+0000
@@ -0,0 +1,11 @@
+drop table if exists t1;
+reset master;
+create table t1 (a int);
+insert into t1 values (1);
+flush logs;
+drop table t1;
+*** must be 1 ***
+select * from t1;
+a
+1
+drop table t1;
=== modified file 'mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result'
--- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-09-06 07:22:50 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-10-09 08:39:43 +0000
@@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1);
INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
Comparing tables master:test.t7 and slave:test.t7
drop table t1, t2, t3, t4, t5, t6, t7;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='MYISAM' ;
+INSERT INTO t1 VALUES (1), (2), (3);
+UPDATE t1 SET a = 10;
+ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
+INSERT INTO t1 VALUES (4);
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
=== modified file 'mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result'
--- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-09-06 07:22:50 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-10-09 08:39:43 +0000
@@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1);
INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
Comparing tables master:test.t7 and slave:test.t7
drop table t1, t2, t3, t4, t5, t6, t7;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='INNODB' ;
+INSERT INTO t1 VALUES (1), (2), (3);
+UPDATE t1 SET a = 10;
+ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
+INSERT INTO t1 VALUES (4);
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
=== added file 'mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules-master.opt'
--- a/mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules-master.opt 1970-01-01 00:00:00
+0000
+++ b/mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules-master.opt 2008-09-03 10:01:18
+0000
@@ -0,0 +1 @@
+--replicate-do-db='impossible_database'
=== added file 'mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules.test'
--- a/mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_binlog_query_filter_rules.test 2008-10-07 08:25:12 +0000
@@ -0,0 +1,32 @@
+# regression test for
+# Bug#36099 replicate-do-db affects replaying RBR events with mysqlbinlog
+# The test verifies that the slave side filtering rule does not affect
+# applying of row-events on master via mysqlbinlog
+
+-- source include/have_log_bin.inc
+-- source include/not_embedded.inc
+-- source include/have_binlog_format_row.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+reset master;
+
+create table t1 (a int);
+insert into t1 values (1);
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+flush logs;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 >
$MYSQLTEST_VARDIR/tmp/bug36099.sql
+
+drop table t1;
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/bug36099.sql"
+
+--echo *** must be 1 ***
+select * from t1;
+
+# cleanup
+
+drop table t1;
+remove_file $MYSQLTEST_VARDIR/tmp/bug36099.sql;
=== modified file 'mysql-test/suite/rpl/t/rpl_ps.test'
--- a/mysql-test/suite/rpl/t/rpl_ps.test 2008-10-07 10:26:19 +0000
+++ b/mysql-test/suite/rpl/t/rpl_ps.test 2008-10-09 08:39:43 +0000
@@ -120,7 +120,6 @@ DROP TABLE t1;
--echo
--sync_slave_with_master
-
--echo
--echo # Connection: slave
--echo
=== modified file 'mysql-test/suite/rpl_ndb_big/r/rpl_ndb_log.result'
--- a/mysql-test/suite/rpl_ndb_big/r/rpl_ndb_log.result 2008-08-04 14:30:50 +0000
+++ b/mysql-test/suite/rpl_ndb_big/r/rpl_ndb_log.result 2008-10-09 08:39:43 +0000
@@ -7,7 +7,7 @@ start slave;
include/stop_slave.inc
reset master;
reset slave;
-reset master;
+start slave;
create table t1(n int not null auto_increment primary key)ENGINE=NDB;
insert into t1 values (NULL);
drop table t1;
=== modified file 'mysql-test/suite/rpl_ndb_big/r/rpl_row_basic_7ndb.result'
--- a/mysql-test/suite/rpl_ndb_big/r/rpl_row_basic_7ndb.result 2008-09-06 07:22:50 +0000
+++ b/mysql-test/suite/rpl_ndb_big/r/rpl_row_basic_7ndb.result 2008-10-09 08:39:43 +0000
@@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1);
INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
Comparing tables master:test.t7 and slave:test.t7
drop table t1, t2, t3, t4, t5, t6, t7;
+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='NDB' ;
+INSERT INTO t1 VALUES (1), (2), (3);
+UPDATE t1 SET a = 10;
+ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
+INSERT INTO t1 VALUES (4);
+Comparing tables master:test.t1 and slave:test.t1
+drop table t1;
=== modified file 'mysql-test/t/create.test'
--- a/mysql-test/t/create.test 2008-08-04 14:30:50 +0000
+++ b/mysql-test/t/create.test 2008-10-09 08:39:43 +0000
@@ -1180,6 +1180,24 @@ SHOW INDEX FROM t1;
DROP TABLE t1;
+#
+# Bug#38821: Assert table->auto_increment_field_not_null failed in open_table()
+#
+CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL);
+INSERT IGNORE INTO t1 (b) VALUES (5);
+
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+ SELECT a FROM t1;
+--error 1062
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+ SELECT a FROM t1;
+--error 1062
+CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
+ SELECT a FROM t1;
+
+DROP TABLE t1, t2;
+
+
--echo End of 5.0 tests
#
=== modified file 'mysql-test/t/default.test'
--- a/mysql-test/t/default.test 2007-02-12 11:41:36 +0000
+++ b/mysql-test/t/default.test 2008-09-03 07:32:43 +0000
@@ -145,5 +145,24 @@ insert into t1 values(default);
drop view v1;
drop table t1;
+#
+# Bug #39002: crash with
+# INSERT ... SELECT ... ON DUPLICATE KEY UPDATE col=DEFAULT
+#
+
+create table t1 (a int unique);
+create table t2 (b int default 10);
+insert into t1 (a) values (1);
+insert into t2 (b) values (1);
+
+insert into t1 (a) select b from t2 on duplicate key update a=default;
+select * from t1;
+
+insert into t1 (a) values (1);
+insert into t1 (a) select b from t2 on duplicate key update a=default(b);
+select * from t1;
+
+drop table t1, t2;
+
--echo End of 5.0 tests.
=== modified file 'mysql-test/t/func_regexp.test'
--- a/mysql-test/t/func_regexp.test 2008-08-15 05:53:25 +0000
+++ b/mysql-test/t/func_regexp.test 2008-09-05 08:36:02 +0000
@@ -64,6 +64,16 @@ drop table t1;
SELECT 1 REGEXP NULL;
+
+#
+# Bug #39021: SELECT REGEXP BINARY NULL never returns
+#
+
+SELECT '' REGEXP BINARY NULL;
+SELECT NULL REGEXP BINARY NULL;
+SELECT 'A' REGEXP BINARY NULL;
+SELECT "ABC" REGEXP BINARY NULL;
+
--echo End of 5.0 tests
=== modified file 'mysql-test/t/grant2.test'
--- a/mysql-test/t/grant2.test 2008-07-10 16:09:39 +0000
+++ b/mysql-test/t/grant2.test 2008-10-06 08:27:36 +0000
@@ -606,7 +606,7 @@ connection conn1;
USE db1;
--error ER_COLUMNACCESS_DENIED_ERROR
SELECT c FROM t2;
---error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_TABLEACCESS_DENIED_ERROR
SELECT * FROM t2;
--error ER_COLUMNACCESS_DENIED_ERROR
SELECT * FROM t1 JOIN t2 USING (b);
=== modified file 'mysql-test/t/status.test'
--- a/mysql-test/t/status.test 2008-05-27 14:51:23 +0000
+++ b/mysql-test/t/status.test 2008-10-09 08:39:43 +0000
@@ -261,6 +261,39 @@ drop function f1;
show status like 'Com%function';
+#
+# Bug#37908: Skipped access right check caused server crash.
+#
+connect (root, localhost, root,,test);
+connection root;
+--disable_warnings
+create database db37908;
+--enable_warnings
+create table db37908.t1(f1 int);
+insert into db37908.t1 values(1);
+grant usage,execute on test.* to mysqltest_1@localhost;
+delimiter |;
+create procedure proc37908() begin select 1; end |
+create function func37908() returns int sql security invoker
+ return (select * from db37908.t1 limit 1)|
+delimiter ;|
+
+connect (user1,localhost,mysqltest_1,,test);
+connection user1;
+
+--error 1142
+select * from db37908.t1;
+--error 1142
+show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
+--error 1142
+show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
+--error 1142
+show function status where name ='func37908' and 1 in (select func37908());
+
+connection root;
+drop database db37908;
+drop procedure proc37908;
+drop function func37908;
# End of 5.1 tests
#
=== modified file 'mysql-test/t/type_datetime.test'
--- a/mysql-test/t/type_datetime.test 2007-12-13 12:59:16 +0000
+++ b/mysql-test/t/type_datetime.test 2008-10-09 08:39:43 +0000
@@ -389,6 +389,22 @@ where id in (select id from t2 as x1 whe
set @@optimizer_switch='';
drop table t1,t2;
+
+#
+# Bug #37526: asymertic operator <=> in trigger
+#
+SELECT
+ CAST('NULL' AS DATE) <=> CAST('2008-01-01' AS DATE) n1,
+ CAST('2008-01-01' AS DATE) <=> CAST('NULL' AS DATE) n2,
+ CAST('NULL' AS DATE) <=> CAST('NULL' AS DATE) n3,
+ CAST('NULL' AS DATE) <> CAST('2008-01-01' AS DATE) n4,
+ CAST('2008-01-01' AS DATE) <> CAST('NULL' AS DATE) n5,
+ CAST('NULL' AS DATE) <> CAST('NULL' AS DATE) n6,
+ CAST('NULL' AS DATE) < CAST('2008-01-01' AS DATE) n7,
+ CAST('2008-01-01' AS DATE) < CAST('NULL' AS DATE) n8,
+ CAST('NULL' AS DATE) < CAST('NULL' AS DATE) n9;
+
+
--echo End of 5.0 tests
#
# Test of storing datetime into date fields
=== modified file 'mysql-test/t/type_set.test'
--- a/mysql-test/t/type_set.test 2008-03-14 20:40:21 +0000
+++ b/mysql-test/t/type_set.test 2008-09-05 15:21:59 +0000
@@ -75,4 +75,23 @@ INSERT INTO t1 VALUES(922337203685477580
SELECT * FROM t1;
DROP TABLE t1;
+#
+# Bug #38701: Crash in String::append when inserting duplicate empty strings
+# an uft8 SET col
+#
+
+CREATE TABLE t1 (
+ set_unique_utf8 set ('a','b','c','d','e','f','g','h','i','j','k','l',
+ 'm','n','o','p','q','r','s','t','u','v','w','x',
+ 'y','z') CHARACTER SET utf8,
+ unique (set_unique_utf8)
+);
+
+INSERT INTO t1 ( set_unique_utf8 ) VALUES ( '' );
+--error ER_DUP_ENTRY
+INSERT INTO t1 ( set_unique_utf8 ) VALUES ( '' );
+
+DROP TABLE t1;
+
+
--echo End of 5.0 tests
=== modified file 'mysql-test/t/view_grant.test'
--- a/mysql-test/t/view_grant.test 2008-06-26 18:56:36 +0000
+++ b/mysql-test/t/view_grant.test 2008-10-09 08:39:43 +0000
@@ -1254,3 +1254,80 @@ DROP USER mysqluser1@localhost;
USE test;
--echo End of 5.1 tests.
+
+#
+# Bug#36086: SELECT * from views don't check column grants
+#
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+
+USE mysqltest1;
+
+CREATE TABLE t1 ( a INT, b INT );
+CREATE TABLE t2 ( a INT, b INT );
+
+CREATE VIEW v1 AS SELECT a, b FROM t1;
+
+GRANT SELECT( a ) ON v1 TO mysqluser1@localhost;
+GRANT UPDATE( b ) ON t2 TO mysqluser1@localhost;
+
+--connect (connection1, localhost, mysqluser1, , test)
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT * FROM mysqltest1.v1;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+CREATE VIEW v1 AS SELECT * FROM mysqltest1.t2;
+
+--disconnect connection1
+
+--connection default
+
+DROP TABLE t1, t2;
+DROP VIEW v1;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
+
+#
+# Bug#35600: Security breach via view, I_S table and prepared
+# statement/stored procedure
+#
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+
+USE mysqltest1;
+
+CREATE VIEW v1 AS SELECT * FROM information_schema.tables LIMIT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 1 AS A;
+
+CREATE VIEW test.v3 AS SELECT 1 AS a;
+
+--connection default
+GRANT SELECT ON mysqltest1.* to mysqluser1@localhost;
+GRANT ALL ON test.* TO mysqluser1@localhost;
+
+--connect (connection1, localhost, mysqluser1, , test)
+PREPARE stmt_v1 FROM "SELECT * FROM mysqltest1.v1";
+PREPARE stmt_v2 FROM "SELECT * FROM mysqltest1.v2";
+
+--connection default
+REVOKE SELECT ON mysqltest1.* FROM mysqluser1@localhost;
+
+--connection connection1
+
+--error ER_TABLEACCESS_DENIED_ERROR
+EXECUTE stmt_v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+EXECUTE stmt_v2;
+--disconnect connection1
+
+--connect (connection2, localhost, mysqluser1,,)
+PREPARE stmt FROM "SELECT a FROM v3";
+EXECUTE stmt;
+--disconnect connection2
+
+--connection default
+DROP VIEW v1, v2;
+DROP DATABASE mysqltest1;
+DROP VIEW test.v3;
+DROP USER mysqluser1@localhost;
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-10-07 10:26:19 +0000
+++ b/sql/handler.cc 2008-10-09 08:39:43 +0000
@@ -2504,7 +2504,7 @@ void handler::print_keydup_error(uint ke
str.append(STRING_WITH_LEN("..."));
}
my_printf_error(ER_DUP_ENTRY, msg,
- MYF(0), str.c_ptr(), table->key_info[key_nr].name);
+ MYF(0), str.c_ptr_safe(), table->key_info[key_nr].name);
}
}
@@ -2575,7 +2575,7 @@ void handler::print_error(int error, myf
str.append(STRING_WITH_LEN("..."));
}
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
- str.c_ptr(), key_nr+1);
+ str.c_ptr_safe(), key_nr+1);
DBUG_VOID_RETURN;
}
textno= ER_DUP_KEY;
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2008-10-07 10:26:19 +0000
+++ b/sql/item.cc 2008-10-09 08:39:43 +0000
@@ -4294,16 +4294,8 @@ bool Item_field::fix_fields(THD *thd, It
if (any_privileges)
{
char *db, *tab;
- if (cached_table->view)
- {
- db= cached_table->view_db.str;
- tab= cached_table->view_name.str;
- }
- else
- {
- db= cached_table->db;
- tab= cached_table->table_name;
- }
+ db= cached_table->get_db_name();
+ tab= cached_table->get_table_name();
if (!(have_privileges= (get_column_grant(thd, &field->table->grant,
db, tab, field_name) &
VIEW_ANY_ACL)))
@@ -6407,6 +6399,13 @@ Item *Item_default_value::transform(Item
{
DBUG_ASSERT(!current_thd->is_stmt_prepare());
+ /*
+ If the value of arg is NULL, then this object represents a constant,
+ so further transformation is unnecessary (and impossible).
+ */
+ if (!arg)
+ return 0;
+
Item *new_item= arg->transform(transformer, args);
if (!new_item)
return 0;
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2008-09-06 07:22:50 +0000
+++ b/sql/item_cmpfunc.cc 2008-10-09 08:39:43 +0000
@@ -1028,19 +1028,24 @@ get_datetime_value(THD *thd, Item ***ite
1 if items are equal or both are null
0 otherwise
If is_nulls_eq is FALSE:
- -1 a < b or one of items is null
+ -1 a < b or at least one item is null
0 a == b
1 a > b
+ See the table:
+ is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
+ a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
+ b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
+ result | 1 | 0 | 0 |0/1|-1 |-1 |-1 |-1/0/1|
*/
int Arg_comparator::compare_datetime()
{
- bool is_null= FALSE;
+ bool a_is_null, b_is_null;
ulonglong a_value, b_value;
/* Get DATE/DATETIME/TIME value of the 'a' item. */
- a_value= (*get_value_func)(thd, &a, &a_cache, *b, &is_null);
- if (!is_nulls_eq && is_null)
+ a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null);
+ if (!is_nulls_eq && a_is_null)
{
if (owner)
owner->null_value= 1;
@@ -1048,14 +1053,15 @@ int Arg_comparator::compare_datetime()
}
/* Get DATE/DATETIME/TIME value of the 'b' item. */
- b_value= (*get_value_func)(thd, &b, &b_cache, *a, &is_null);
- if (is_null)
+ b_value= (*get_value_func)(thd, &b, &b_cache, *a, &b_is_null);
+ if (a_is_null || b_is_null)
{
if (owner)
owner->null_value= is_nulls_eq ? 0 : 1;
- return is_nulls_eq ? 1 : -1;
+ return is_nulls_eq ? (a_is_null == b_is_null) : -1;
}
+ /* Here we have two not-NULL values. */
if (owner)
owner->null_value= 0;
@@ -4562,8 +4568,20 @@ void Item_func_like::cleanup()
#ifdef USE_REGEX
-bool
-Item_func_regex::regcomp(bool send_error)
+/**
+ @brief Compile regular expression.
+
+ @param[in] send_error send error message if any.
+
+ @details Make necessary character set conversion then
+ compile regular expression passed in the args[1].
+
+ @retval 0 success.
+ @retval 1 error occurred.
+ @retval -1 given null regular expression.
+ */
+
+int Item_func_regex::regcomp(bool send_error)
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin);
@@ -4571,12 +4589,12 @@ Item_func_regex::regcomp(bool send_error
int error;
if (args[1]->null_value)
- return TRUE;
+ return -1;
if (regex_compiled)
{
if (!stringcmp(res, &prev_regexp))
- return FALSE;
+ return 0;
prev_regexp.copy(*res);
my_regfree(&preg);
regex_compiled= 0;
@@ -4588,7 +4606,7 @@ Item_func_regex::regcomp(bool send_error
uint dummy_errors;
if (conv.copy(res->ptr(), res->length(), res->charset(),
regex_lib_charset, &dummy_errors))
- return TRUE;
+ return 1;
res= &conv;
}
@@ -4600,10 +4618,10 @@ Item_func_regex::regcomp(bool send_error
(void) my_regerror(error, &preg, buff, sizeof(buff));
my_error(ER_REGEXP_ERROR, MYF(0), buff);
}
- return TRUE;
+ return 1;
}
regex_compiled= 1;
- return FALSE;
+ return 0;
}
@@ -4641,13 +4659,14 @@ Item_func_regex::fix_fields(THD *thd, It
const_item_cache=args[0]->const_item() && args[1]->const_item();
if (!regex_compiled && args[1]->const_item())
{
- if (args[1]->null_value)
+ int comp_res= regcomp(TRUE);
+ if (comp_res == -1)
{ // Will always return NULL
maybe_null=1;
fixed= 1;
return FALSE;
}
- if (regcomp(TRUE))
+ else if (comp_res)
return TRUE;
regex_is_const= 1;
maybe_null= args[0]->maybe_null;
=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h 2008-03-05 10:32:49 +0000
+++ b/sql/item_cmpfunc.h 2008-10-09 08:39:43 +0000
@@ -1404,7 +1404,7 @@ class Item_func_regex :public Item_bool_
CHARSET_INFO *regex_lib_charset;
int regex_lib_flags;
String conv;
- bool regcomp(bool send_error);
+ int regcomp(bool send_error);
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-10-07 10:26:19 +0000
+++ b/sql/log.cc 2008-10-09 08:39:43 +0000
@@ -2171,6 +2171,7 @@ binlog_end_trans(THD *thd, binlog_trx_da
If rolling back a statement in a transaction, we truncate the
transaction cache to remove the statement.
*/
+ thd->binlog_remove_pending_rows_event(TRUE);
if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
{
trx_data->reset();
@@ -5112,6 +5113,31 @@ THD::binlog_set_pending_rows_event(Rows_
}
+/**
+ Remove the pending rows event, discarding any outstanding rows.
+
+ If there is no pending rows event available, this is effectively a
+ no-op.
+ */
+int
+MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd)
+{
+ DBUG_ENTER(__FUNCTION__);
+
+ binlog_trx_data *const trx_data=
+ (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+
+ DBUG_ASSERT(trx_data);
+
+ if (Rows_log_event* pending= trx_data->pending())
+ {
+ delete pending;
+ trx_data->set_pending(NULL);
+ }
+
+ DBUG_RETURN(0);
+}
+
/*
Moves the last bunch of rows from the pending Rows event to the binlog
(either cached binlog if transaction, or disk binlog). Sets a new pending
=== modified file 'sql/log.h'
--- a/sql/log.h 2008-10-07 10:26:19 +0000
+++ b/sql/log.h 2008-10-09 08:39:43 +0000
@@ -417,6 +417,7 @@ public:
void update_table_map_version() { ++m_table_map_version; }
int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event);
+ int remove_pending_rows_event(THD *thd);
#endif /* !defined(MYSQL_CLIENT) */
void reset_bytes_written()
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2008-10-07 10:26:19 +0000
+++ b/sql/log_event.cc 2008-10-09 08:39:43 +0000
@@ -7886,8 +7886,9 @@ int Table_map_log_event::do_apply_event(
int error= 0;
- if (!rpl_filter->db_ok(table_list->db) ||
- (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list)))
+ if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
+ (!rpl_filter->db_ok(table_list->db) ||
+ (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
{
my_free(memory, MYF(MY_WME));
}
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2008-10-07 10:26:19 +0000
+++ b/sql/set_var.cc 2008-10-09 08:39:43 +0000
@@ -1224,6 +1224,21 @@ void fix_slave_exec_mode(enum_var_type t
DBUG_VOID_RETURN;
}
+
+bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
+ /*
+ All variables that affect writing to binary log (either format or
+ turning logging on and off) use the same checking. We call the
+ superclass ::check function to assign the variable correctly, and
+ then check the value.
+ */
+ bool result= sys_var_thd_enum::check(thd, var);
+ if (!result)
+ result= check_log_update(thd, var);
+ return result;
+}
+
+
bool sys_var_thd_binlog_format::is_readonly() const
{
/*
=== modified file 'sql/set_var.h'
--- a/sql/set_var.h 2008-10-07 10:26:19 +0000
+++ b/sql/set_var.h 2008-10-09 08:39:43 +0000
@@ -1230,6 +1230,7 @@ public:
&binlog_format_typelib,
fix_binlog_format_after_update)
{};
+ bool check(THD *thd, set_var *var);
bool is_readonly() const;
};
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2008-10-07 10:26:19 +0000
+++ b/sql/sql_acl.cc 2008-10-09 08:39:43 +0000
@@ -3091,12 +3091,8 @@ int mysql_table_grant(THD *thd, TABLE_LI
continue; // Add next user
}
- db_name= (table_list->view_db.length ?
- table_list->view_db.str :
- table_list->db);
- table_name= (table_list->view_name.length ?
- table_list->view_name.str :
- table_list->table_name);
+ db_name= table_list->get_db_name();
+ table_name= table_list->get_table_name();
/* Find/create cached table grant */
grant_table= table_hash_search(Str->host.str, NullS, db_name,
@@ -3924,8 +3920,8 @@ bool check_grant(THD *thd, ulong want_ac
if (!want_access)
continue; // ok
- if (!(~table->grant.privilege & want_access) ||
- table->derived || table->schema_table)
+ if (!(~table->grant.privilege & want_access) ||
+ table->is_anonymous_derived_table() || table->schema_table)
{
/*
It is subquery in the FROM clause. VIEW set table->derived after
@@ -3943,8 +3939,8 @@ bool check_grant(THD *thd, ulong want_ac
continue;
}
if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
- table->db, sctx->priv_user,
- table->table_name,0)))
+ table->get_db_name(), sctx->priv_user,
+ table->get_table_name(), FALSE)))
{
want_access &= ~table->grant.privilege;
goto err; // No grants
@@ -3985,7 +3981,7 @@ err:
command,
sctx->priv_user,
sctx->host_or_ip,
- table ? table->table_name : "unknown");
+ table ? table->get_table_name() : "unknown");
}
DBUG_RETURN(TRUE);
}
@@ -4229,7 +4225,7 @@ bool check_column_grant_in_table_ref(THD
@retval 1 Falure
@details This function walks over the columns of a table reference
The columns may originate from different tables, depending on the kind of
- table reference, e.g. join.
+ table reference, e.g. join, view.
For each table it will retrieve the grant information and will use it
to check the required access privileges for the fields requested from it.
*/
@@ -4244,6 +4240,11 @@ bool check_grant_all_columns(THD *thd, u
GRANT_INFO *grant;
/* Initialized only to make gcc happy */
GRANT_TABLE *grant_table= NULL;
+ /*
+ Flag that gets set if privilege checking has to be performed on column
+ level.
+ */
+ bool using_column_privileges= FALSE;
rw_rdlock(&LOCK_grant);
@@ -4251,10 +4252,10 @@ bool check_grant_all_columns(THD *thd, u
{
const char *field_name= fields->name();
- if (table_name != fields->table_name())
+ if (table_name != fields->get_table_name())
{
- table_name= fields->table_name();
- db_name= fields->db_name();
+ table_name= fields->get_table_name();
+ db_name= fields->get_db_name();
grant= fields->grant();
/* get a fresh one for each table */
want_access= want_access_arg & ~grant->privilege;
@@ -4280,6 +4281,8 @@ bool check_grant_all_columns(THD *thd, u
GRANT_COLUMN *grant_column=
column_hash_search(grant_table, field_name,
(uint) strlen(field_name));
+ if (grant_column)
+ using_column_privileges= TRUE;
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
@@ -4292,12 +4295,21 @@ err:
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
- command,
- sctx->priv_user,
- sctx->host_or_ip,
- fields->name(),
- table_name);
+ /*
+ Do not give an error message listing a column name unless the user has
+ privilege to see all columns.
+ */
+ if (using_column_privileges)
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command, sctx->priv_user,
+ sctx->host_or_ip, table_name);
+ else
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ sctx->priv_user,
+ sctx->host_or_ip,
+ fields->name(),
+ table_name);
return 1;
}
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-10-07 10:26:19 +0000
+++ b/sql/sql_base.cc 2008-10-09 08:39:43 +0000
@@ -6816,9 +6816,34 @@ insert_fields(THD *thd, Name_resolution_
continue;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Ensure that we have access rights to all fields to be inserted. */
- if (!((table && (table->grant.privilege & SELECT_ACL) ||
- tables->view && (tables->grant.privilege & SELECT_ACL)))
&&
+ /*
+ Ensure that we have access rights to all fields to be inserted. Under
+ some circumstances, this check may be skipped.
+
+ - If any_privileges is true, skip the check.
+
+ - If the SELECT privilege has been found as fulfilled already for both
+ the TABLE and TABLE_LIST objects (and both of these exist, of
+ course), the check is skipped.
+
+ - If the SELECT privilege has been found fulfilled for the TABLE object
+ and the TABLE_LIST represents a derived table other than a view (see
+ below), the check is skipped.
+
+ - If the TABLE_LIST object represents a view, we may skip checking if
+ the SELECT privilege has been found fulfilled for it, regardless of
+ the TABLE object.
+
+ - If there is no TABLE object, the test is skipped if either
+ * the TABLE_LIST does not represent a view, or
+ * the SELECT privilege has been found fulfilled.
+
+ A TABLE_LIST that is not a view may be a subquery, an
+ information_schema table, or a nested table reference. See the comment
+ for TABLE_LIST.
+ */
+ if (!(table && !tables->view && (table->grant.privilege &
SELECT_ACL) ||
+ tables->view && (tables->grant.privilege & SELECT_ACL))
&&
!any_privileges)
{
field_iterator.set(tables);
@@ -6872,19 +6897,19 @@ insert_fields(THD *thd, Name_resolution_
tables->is_natural_join);
DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
Item_field *fld= (Item_field*) item;
- const char *field_table_name= field_iterator.table_name();
+ const char *field_table_name= field_iterator.get_table_name();
if (!tables->schema_table &&
!(fld->have_privileges=
(get_column_grant(thd, field_iterator.grant(),
- field_iterator.db_name(),
+ field_iterator.get_db_name(),
field_table_name, fld->field_name) &
VIEW_ANY_ACL)))
{
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY",
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY",
thd->security_ctx->priv_user,
thd->security_ctx->host_or_ip,
- fld->field_name, field_table_name);
+ field_table_name);
DBUG_RETURN(TRUE);
}
}
=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc 2008-08-27 12:49:58 +0000
+++ b/sql/sql_cache.cc 2008-10-09 08:39:43 +0000
@@ -2648,7 +2648,7 @@ Query_cache::register_tables_from_list(T
tables_used;
tables_used= tables_used->next_global, n++, block_table++)
{
- if (tables_used->derived && !tables_used->view)
+ if (tables_used->is_anonymous_derived_table())
{
DBUG_PRINT("qcache", ("derived table skipped"));
n--;
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-10-07 10:26:19 +0000
+++ b/sql/sql_class.cc 2008-10-09 08:39:43 +0000
@@ -3521,6 +3521,21 @@ int THD::binlog_delete_row(TABLE* table,
}
+int THD::binlog_remove_pending_rows_event(bool clear_maps)
+{
+ DBUG_ENTER(__FUNCTION__);
+
+ if (!mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ mysql_bin_log.remove_pending_rows_event(this);
+
+ if (clear_maps)
+ binlog_table_maps= 0;
+
+ DBUG_RETURN(0);
+}
+
int THD::binlog_flush_pending_rows_event(bool stmt_end)
{
DBUG_ENTER("THD::binlog_flush_pending_rows_event");
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-10-07 10:26:19 +0000
+++ b/sql/sql_class.h 2008-10-09 08:39:43 +0000
@@ -1524,9 +1524,14 @@ public:
Rows_log_event* binlog_get_pending_rows_event() const;
void binlog_set_pending_rows_event(Rows_log_event* ev);
int binlog_flush_pending_rows_event(bool stmt_end);
+ int binlog_remove_pending_rows_event(bool clear_maps);
private:
- uint binlog_table_maps; // Number of table maps currently in the binlog
+ /*
+ Number of outstanding table maps, i.e., table maps in the
+ transaction cache.
+ */
+ uint binlog_table_maps;
enum enum_binlog_flag {
BINLOG_FLAG_UNSAFE_STMT_PRINTED,
=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc 2007-12-12 15:44:48 +0000
+++ b/sql/sql_derived.cc 2008-10-09 08:39:43 +0000
@@ -73,29 +73,59 @@ out:
}
-/*
- Create temporary table structure (but do not fill it)
-
- SYNOPSIS
- mysql_derived_prepare()
- thd Thread handle
- lex LEX for this thread
- orig_table_list TABLE_LIST for the upper SELECT
-
- IMPLEMENTATION
- Derived table is resolved with temporary table.
-
- After table creation, the above TABLE_LIST is updated with a new table.
-
- This function is called before any command containing derived table
- is executed.
-
- Derived tables is stored in thd->derived_tables and freed in
- close_thread_tables()
+/**
+ @brief Create temporary table structure (but do not fill it).
- RETURN
- FALSE OK
- TRUE Error
+ @param thd Thread handle
+ @param lex LEX for this thread
+ @param orig_table_list TABLE_LIST for the upper SELECT
+
+ @details
+
+ This function is called before any command containing derived tables is
+ executed. Currently the function is used for derived tables, i.e.
+
+ - Anonymous derived tables, or
+ - Named derived tables (aka views) with the @c TEMPTABLE algorithm.
+
+ The table reference, contained in @c orig_table_list, is updated with the
+ fields of a new temporary table.
+
+ Derived tables are stored in @c thd->derived_tables and closed by
+ close_thread_tables().
+
+ This function is part of the procedure that starts in
+ open_and_lock_tables(), a procedure that - among other things - introduces
+ new table and table reference objects (to represent derived tables) that
+ don't exist in the privilege database. This means that normal privilege
+ checking cannot handle them. Hence this function does some extra tricks in
+ order to bypass normal privilege checking, by exploiting the fact that the
+ current state of privilege verification is attached as GRANT_INFO structures
+ on the relevant TABLE and TABLE_REF objects.
+
+ For table references, the current state of accrued access is stored inside
+ TABLE_LIST::grant. Hence this function must update the state of fulfilled
+ privileges for the new TABLE_LIST, an operation which is normally performed
+ exclusively by the table and database access checking functions,
+ check_access() and check_grant(), respectively. This modification is done
+ for both views and anonymous derived tables: The @c SELECT privilege is set
+ as fulfilled by the user. However, if a view is referenced and the table
+ reference is queried against directly (see TABLE_LIST::referencing_view),
+ the state of privilege checking (GRANT_INFO struct) is copied as-is to the
+ temporary table.
+
+ This function implements a signature called "derived table processor", and
+ is passed as a function pointer to mysql_handle_derived().
+
+ @note This function sets @c SELECT_ACL for @c TEMPTABLE views as well as
+ anonymous derived tables, but this is ok since later access checking will
+ distinguish between them.
+
+ @see mysql_handle_derived(), mysql_derived_filling(), GRANT_INFO
+
+ @return
+ false OK
+ true Error
*/
bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2008-10-07 10:26:19 +0000
+++ b/sql/sql_insert.cc 2008-10-09 08:39:43 +0000
@@ -3134,9 +3134,10 @@ bool select_insert::send_data(List<Item>
DBUG_RETURN(1);
}
}
-
+
error= write_record(thd, table, &info);
-
+ table->auto_increment_field_not_null= FALSE;
+
if (!error)
{
if (table->triggers || info.handle_duplicates == DUP_UPDATE)
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-10-07 10:26:19 +0000
+++ b/sql/sql_parse.cc 2008-10-09 08:39:43 +0000
@@ -1980,13 +1980,15 @@ mysql_execute_command(THD *thd)
#endif
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
- res= execute_sqlcom_select(thd, all_tables);
+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+ res= execute_sqlcom_select(thd, all_tables);
break;
case SQLCOM_SHOW_STATUS:
{
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var;
- res= execute_sqlcom_select(thd, all_tables);
+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+ res= execute_sqlcom_select(thd, all_tables);
/* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
@@ -4656,6 +4658,8 @@ bool check_single_table_access(THD *thd,
/* Show only 1 table for check_grant */
if (!(all_tables->belong_to_view &&
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
+ !(all_tables->view &&
+ all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) &&
check_grant(thd, privilege, all_tables, 0, 1, no_errors))
goto deny;
@@ -5052,15 +5056,23 @@ check_table_access(THD *thd, ulong requi
continue;
}
- if (tables->derived ||
- (tables->table && tables->table->s &&
(int)tables->table->s->tmp_table))
+ if (tables->is_anonymous_derived_table() ||
+ (tables->table && (int)tables->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
if ((sctx->master_access & want_access) ==
want_access && thd->db)
tables->grant.privilege= want_access;
- else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
- 0, no_errors, 0))
+ else if (tables->db && thd->db && strcmp(tables->db,
thd->db) == 0)
+ {
+ if (check_access(thd, want_access, tables->get_db_name(),
+ &tables->grant.privilege, 0, no_errors,
+ test(tables->schema_table)))
+ goto deny; // Access denied
+ }
+ else if (check_access(thd, want_access, tables->get_db_name(),
+ &tables->grant.privilege, 0, no_errors,
+ test(tables->schema_table)))
goto deny;
}
thd->security_ctx= backup_ctx;
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2008-10-07 10:26:19 +0000
+++ b/sql/table.cc 2008-10-09 08:39:43 +0000
@@ -3131,16 +3131,27 @@ void TABLE_LIST::calc_md5(char *buffer)
}
-/*
- set underlying TABLE for table place holder of VIEW
+/**
+ @brief Set underlying table for table place holder of view.
- DESCRIPTION
- Replace all views that only uses one table with the table itself.
- This allows us to treat the view as a simple table and even update
- it (it is a kind of optimisation)
+ @details
- SYNOPSIS
- TABLE_LIST::set_underlying_merge()
+ Replace all views that only use one table with the table itself. This
+ allows us to treat the view as a simple table and even update it (it is a
+ kind of optimization).
+
+ @note
+
+ This optimization is potentially dangerous as it makes views
+ masquerade as base tables: Views don't have the pointer TABLE_LIST::table
+ set to non-@c NULL.
+
+ We may have the case where a view accesses tables not normally accessible
+ in the current Security_context (only in the definer's
+ Security_context). According to the table's GRANT_INFO (TABLE::grant),
+ access is fulfilled, but this is implicitly meant in the definer's security
+ context. Hence we must never look at only a TABLE's GRANT_INFO without
+ looking at the one of the referring TABLE_LIST.
*/
void TABLE_LIST::set_underlying_merge()
@@ -4220,7 +4231,7 @@ void Field_iterator_table_ref::next()
}
-const char *Field_iterator_table_ref::table_name()
+const char *Field_iterator_table_ref::get_table_name()
{
if (table_ref->view)
return table_ref->view_name.str;
@@ -4233,7 +4244,7 @@ const char *Field_iterator_table_ref::ta
}
-const char *Field_iterator_table_ref::db_name()
+const char *Field_iterator_table_ref::get_db_name()
{
if (table_ref->view)
return table_ref->view_db.str;
=== modified file 'sql/table.h'
--- a/sql/table.h 2008-10-07 10:26:19 +0000
+++ b/sql/table.h 2008-10-09 08:39:43 +0000
@@ -69,13 +69,63 @@ typedef struct st_order {
table_map used, depend_map;
} ORDER;
+/**
+ @brief The current state of the privilege checking process for the current
+ user, SQL statement and SQL object.
+
+ @details The privilege checking process is divided into phases depending on
+ the level of the privilege to be checked and the type of object to be
+ accessed. Due to the mentioned scattering of privilege checking
+ functionality, it is necessary to keep track of the state of the
+ process. This information is stored in privilege, want_privilege, and
+ orig_want_privilege.
+
+ A GRANT_INFO also serves as a cache of the privilege hash tables. Relevant
+ members are grant_table and version.
+ */
typedef struct st_grant_info
{
+ /**
+ @brief A copy of the privilege information regarding the current host,
+ database, object and user.
+
+ @details The version of this copy is found in GRANT_INFO::version.
+ */
GRANT_TABLE *grant_table;
+ /**
+ @brief Used for cache invalidation when caching privilege information.
+
+ @details The privilege information is stored on disk, with dedicated
+ caches residing in memory: table-level and column-level privileges,
+ respectively, have their own dedicated caches.
+
+ The GRANT_INFO works as a level 1 cache with this member updated to the
+ current value of the global variable @c grant_version (@c static variable
+ in sql_acl.cc). It is updated Whenever the GRANT_INFO is refreshed from
+ the level 2 cache. The level 2 cache is the @c column_priv_hash structure
+ (@c static variable in sql_acl.cc)
+
+ @see grant_version
+ */
uint version;
+ /**
+ @brief The set of privileges that the current user has fulfilled for a
+ certain host, database, and object.
+
+ @details This field is continually updated throughout the access checking
+ process. In each step the "wanted privilege" is checked against the
+ fulfilled privileges. When/if the intersection of these sets is empty,
+ access is granted.
+
+ The set is implemented as a bitmap, with the bits defined in sql_acl.h.
+ */
ulong privilege;
+ /**
+ @brief the set of privileges that the current user needs to fulfil in
+ order to carry out the requested operation.
+ */
ulong want_privilege;
- /*
+ /**
Stores the requested access acl of top level tables list. Is used to
check access rights to the underlying tables of a view.
*/
@@ -1092,6 +1142,27 @@ struct TABLE_LIST
can see this lists can't be merged)
*/
TABLE_LIST *correspondent_table;
+ /**
+ @brief Normally, this field is non-null for anonymous derived tables only.
+
+ @details This field is set to non-null for
+
+ - Anonymous derived tables, In this case it points to the SELECT_LEX_UNIT
+ representing the derived table. E.g. for a query
+
+ @verbatim SELECT * FROM (SELECT a FROM t1) b @endverbatim
+
+ For the @c TABLE_LIST representing the derived table @c b, @c derived
+ points to the SELECT_LEX_UNIT representing the result of the query within
+ parenteses.
+
+ - Views. This is set for views with @verbatim ALGORITHM = TEMPTABLE
+ @endverbatim by mysql_make_view().
+
+ @note Inside views, a subquery in the @c FROM clause is not allowed.
+ @note Do not use this field to separate views/base tables/anonymous
+ derived tables. Use TABLE_LIST::is_anonymous_derived_table().
+ */
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
st_select_lex *schema_select_lex;
@@ -1157,7 +1228,15 @@ struct TABLE_LIST
ulonglong file_version; /* version of file's field set */
ulonglong updatable_view; /* VIEW can be updated */
ulonglong revision; /* revision control number */
- ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
+ /**
+ @brief The declared algorithm, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ ulonglong algorithm;
ulonglong view_suid; /* view is suid (TRUE dy default) */
ulonglong with_check; /* WITH CHECK OPTION */
/*
@@ -1165,7 +1244,15 @@ struct TABLE_LIST
algorithm)
*/
uint8 effective_with_check;
- uint8 effective_algorithm; /* which algorithm was really used */
+ /**
+ @brief The view algorithm that is actually used, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ uint8 effective_algorithm;
GRANT_INFO grant;
/* data need by some engines in query cache*/
ulonglong engine_data;
@@ -1379,6 +1466,26 @@ struct TABLE_LIST
m_table_ref_version= s->get_table_ref_version();
}
+ /**
+ @brief True if this TABLE_LIST represents an anonymous derived table,
+ i.e. the result of a subquery.
+ */
+ bool is_anonymous_derived_table() const { return derived && !view; }
+
+ /**
+ @brief Returns the name of the database that the referenced table belongs
+ to.
+ */
+ char *get_db_name() { return view != NULL ? view_db.str : db; }
+
+ /**
+ @brief Returns the name of the table that this TABLE_LIST represents.
+
+ @details The unqualified table name or view name for a table or view,
+ respectively.
+ */
+ char *get_table_name() { return view != NULL ? view_name.str : table_name; }
+
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
@@ -1508,8 +1615,8 @@ public:
bool end_of_fields()
{ return (table_ref == last_leaf && field_it->end_of_fields()); }
const char *name() { return field_it->name(); }
- const char *table_name();
- const char *db_name();
+ const char *get_table_name();
+ const char *get_db_name();
GRANT_INFO *grant();
Item *create_item(THD *thd) { return field_it->create_item(thd); }
Field *field() { return field_it->field(); }
| Thread |
|---|
| • bzr commit into mysql-6.0-rpl branch (mats:2703) | Mats Kindahl | 9 Oct |