3164 Bjorn Munch 2011-02-04 [merge]
upmerge 47141
modified:
mysql-test/mysql-test-run.pl
3163 Bjorn Munch 2011-02-04 [merge]
merge from 5.5 main
added:
mysql-test/extra/rpl_tests/rpl_insert_duplicate.test
mysql-test/r/filesort_debug.result
mysql-test/suite/innodb/r/innodb_bug30423.result
mysql-test/suite/innodb/t/innodb_bug30423.test
mysql-test/suite/rpl/r/rpl_insert_duplicate.result
mysql-test/suite/rpl/t/rpl_insert_duplicate.test
mysql-test/t/filesort_debug.test
modified:
config.h.cmake
configure.cmake
include/my_sys.h
include/my_time.h
mysql-test/extra/rpl_tests/rpl_insert_ignore.test
mysql-test/include/commit.inc
mysql-test/include/gis_keys.inc
mysql-test/include/mtr_warnings.sql
mysql-test/include/plugin.defs
mysql-test/r/commit_1innodb.result
mysql-test/r/csv_not_null.result
mysql-test/r/func_group.result
mysql-test/r/func_time.result
mysql-test/r/gis.result
mysql-test/r/join_outer.result
mysql-test/r/not_embedded_server.result
mysql-test/r/order_by.result
mysql-test/r/plugin_auth.result
mysql-test/r/range.result
mysql-test/r/symlink.result
mysql-test/suite/innodb/r/innodb_gis.result
mysql-test/suite/innodb/t/innodb_bug56143.test
mysql-test/suite/rpl/r/rpl_insert_ignore.result
mysql-test/suite/rpl/r/rpl_log_pos.result
mysql-test/suite/rpl/t/disabled.def
mysql-test/suite/rpl/t/rpl_insert_ignore.test
mysql-test/suite/sys_vars/r/all_vars.result
mysql-test/t/csv_not_null.test
mysql-test/t/func_group.test
mysql-test/t/func_time.test
mysql-test/t/join_outer.test
mysql-test/t/not_embedded_server.test
mysql-test/t/order_by.test
mysql-test/t/plugin_auth.test
mysql-test/t/range.test
mysql-test/t/symlink.test
mysql-test/t/variables.test
plugin/auth/test_plugin.c
regex/my_regex.h
regex/regcomp.c
regex/reginit.c
sql-common/client.c
sql-common/my_time.c
sql/field.cc
sql/filesort.cc
sql/item_sum.cc
sql/item_sum.h
sql/mysqld.cc
sql/protocol.cc
sql/share/errmsg-utf8.txt
sql/sql_class.h
sql/sql_insert.cc
sql/sql_repl.cc
sql/sql_select.cc
sql/sys_vars.cc
sql/unireg.h
storage/innobase/btr/btr0btr.c
storage/innobase/btr/btr0cur.c
storage/innobase/btr/btr0sea.c
storage/innobase/buf/buf0buddy.c
storage/innobase/buf/buf0buf.c
storage/innobase/buf/buf0lru.c
storage/innobase/dict/dict0dict.c
storage/innobase/handler/ha_innodb.cc
storage/innobase/ibuf/ibuf0ibuf.c
storage/innobase/include/btr0cur.h
storage/innobase/include/buf0buf.h
storage/innobase/include/buf0lru.h
storage/innobase/include/dict0mem.h
storage/innobase/include/dict0types.h
storage/innobase/include/rem0cmp.h
storage/innobase/include/rem0cmp.ic
storage/innobase/include/srv0srv.h
storage/innobase/include/sync0rw.h
storage/innobase/include/trx0rseg.h
storage/innobase/include/trx0trx.h
storage/innobase/include/univ.i
storage/innobase/mem/mem0mem.c
storage/innobase/mtr/mtr0log.c
storage/innobase/page/page0zip.c
storage/innobase/rem/rem0cmp.c
storage/innobase/row/row0merge.c
storage/innobase/row/row0upd.c
storage/innobase/row/row0vers.c
storage/innobase/srv/srv0srv.c
storage/innobase/sync/sync0arr.c
storage/innobase/sync/sync0rw.c
storage/innobase/sync/sync0sync.c
storage/innobase/trx/trx0trx.c
3162 Bjorn Munch 2011-01-29 [merge]
null upmerge
=== modified file 'config.h.cmake'
--- a/config.h.cmake 2011-01-04 10:23:45 +0000
+++ b/config.h.cmake 2011-02-02 18:13:28 +0000
@@ -614,4 +614,9 @@
#define PROTOCOL_VERSION 10
+/* time_t related defines */
+
+#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@
+#cmakedefine TIME_T_UNSIGNED @TIME_T_UNSIGNED@
+
#endif
=== modified file 'configure.cmake'
--- a/configure.cmake 2010-12-21 12:00:26 +0000
+++ b/configure.cmake 2011-02-02 18:13:28 +0000
@@ -574,6 +574,7 @@ MY_CHECK_TYPE_SIZE(uint32 UINT32)
MY_CHECK_TYPE_SIZE(u_int32_t U_INT32_T)
MY_CHECK_TYPE_SIZE(int64 INT64)
MY_CHECK_TYPE_SIZE(uint64 UINT64)
+MY_CHECK_TYPE_SIZE(time_t TIME_T)
SET (CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
MY_CHECK_TYPE_SIZE(bool BOOL)
SET(CMAKE_EXTRA_INCLUDE_FILES)
@@ -593,6 +594,16 @@ ENDIF()
# Code tests
#
+# check whether time_t is unsigned
+CHECK_C_SOURCE_COMPILES("
+int main()
+{
+ int array[(((time_t)-1) > 0) ? 1 : -1];
+ return 0;
+}"
+TIME_T_UNSIGNED)
+
+
CHECK_C_SOURCE_COMPILES("
#ifdef _WIN32
#include <winsock2.h>
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2011-01-17 07:44:37 +0000
+++ b/include/my_sys.h 2011-02-02 11:54:49 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -104,7 +104,7 @@ typedef struct my_aio_result {
#define ME_HOLDTANG 8 /* Don't delete last keys */
#define ME_WAITTOT 16 /* Wait for errtime secs of for a action */
#define ME_WAITTANG 32 /* Wait for a user action */
-#define ME_NOREFRESH 64 /* Dont refresh screen */
+#define ME_NOREFRESH 64 /* Write the error message to error log */
#define ME_NOINPUT 128 /* Dont use the input libary */
#define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */
#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
=== modified file 'include/my_time.h'
--- a/include/my_time.h 2010-07-15 11:28:41 +0000
+++ b/include/my_time.h 2011-02-02 18:13:28 +0000
@@ -50,6 +50,19 @@ typedef long my_time_t;
/* two-digit years < this are 20..; >= this are 19.. */
#define YY_PART_YEAR 70
+/*
+ check for valid times only if the range of time_t is greater than
+ the range of my_time_t
+*/
+#if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED)
+# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \
+ ((x) <= TIMESTAMP_MAX_VALUE && \
+ (x) >= TIMESTAMP_MIN_VALUE)
+#else
+# define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \
+ ((x) >= TIMESTAMP_MIN_VALUE)
+#endif
+
/* Flags to str_to_datetime */
#define TIME_FUZZY_DATE 1
#define TIME_DATETIME_ONLY 2
=== added file 'mysql-test/extra/rpl_tests/rpl_insert_duplicate.test'
--- a/mysql-test/extra/rpl_tests/rpl_insert_duplicate.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_insert_duplicate.test 2011-01-31 13:11:05 +0000
@@ -0,0 +1,59 @@
+# BUG#59338 Inconsistency in binlog for statements that don't change any rows STATEMENT SBR
+# In SBR, if a statement does not fail, it is always written to the binary log,
+# regardless if rows are changed or not. If there is a failure, a statement is
+# only written to the binary log if a non-transactional (.e.g. MyIsam) engine
+# is updated. INSERT ON DUPLICATE KEY UPDATE was not following the rule above
+# and was not written to the binary log, if then engine was Innodb.
+#
+# In this test case, we check if INSERT ON DUPLICATE KEY UPDATE that does not
+# change anything is still written to the binary log.
+
+# Prepare environment
+--connection master
+
+eval CREATE TABLE t1 (
+ a INT UNSIGNED NOT NULL PRIMARY KEY
+) ENGINE=$engine_type;
+
+eval CREATE TABLE t2 (
+ a INT UNSIGNED
+) ENGINE=$engine_type;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+
+# An insert duplicate that does not update anything must be written to the binary
+# log in SBR and MIXED modes. We check this property by summing a before and after
+# the update and comparing the binlog positions. The sum should be the same at both
+# points and the statement should be in the binary log.
+--let $binlog_file= query_get_value("SHOW MASTER STATUS", File, 1)
+--let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1)
+--let $statement_file=INSERT INTO t1 SELECT t2.a FROM t2 ORDER BY t2.a ON DUPLICATE KEY UPDATE t1.a= t1.a
+--eval $statement_file
+
+--let $assert_cond= SUM(a) = 1 FROM t1
+--let $assert_text= Sum of elements in t1 should be 1.
+--source include/assert.inc
+
+if (`SELECT @@BINLOG_FORMAT = 'ROW'`)
+{
+ --let $binlog_position_cmp= =
+ --let $assert_cond= [SHOW MASTER STATUS, Position, 1] $binlog_position_cmp $binlog_start
+ --let $assert_text= In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.
+}
+if (`SELECT @@BINLOG_FORMAT != 'ROW'`)
+{
+ --let $assert_cond= \'[\'SHOW BINLOG EVENTS IN "$binlog_file" FROM $binlog_start LIMIT 1, 1\', Info, 1]\' LIKE \'%$statement_file\'
+ --let $assert_text= In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.
+}
+--source include/assert.inc
+
+# Compare master and slave
+--sync_slave_with_master
+--let $diff_tables= master:test.t1 , slave:test.t1
+--source include/diff_tables.inc
+
+# Clean up
+--connection master
+drop table t1, t2;
+--sync_slave_with_master
=== modified file 'mysql-test/extra/rpl_tests/rpl_insert_ignore.test'
--- a/mysql-test/extra/rpl_tests/rpl_insert_ignore.test 2009-11-03 19:02:56 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_insert_ignore.test 2011-01-31 13:11:05 +0000
@@ -5,6 +5,7 @@
# Slave needs to be started with --innodb to store table in InnoDB.
# Same test for MyISAM (which had no bug).
+--connection master
eval CREATE TABLE t1 (
a int unsigned not null auto_increment primary key,
b int unsigned,
@@ -32,40 +33,44 @@ INSERT INTO t2 VALUES (5, 4);
INSERT INTO t2 VALUES (6, 6);
INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
+--let $assert_cond= COUNT(*) = 6 FROM t1
+--let $assert_text= Count of elements in t1 should be 6.
+--source include/assert.inc
+
+# Compare master and slave
+--sync_slave_with_master
+--let $diff_tables= master:test.t1 , slave:test.t1
+--source include/diff_tables.inc
+
+# BUG#59338 Inconsistency in binlog for statements that don't change any rows STATEMENT SBR
+# An insert ignore that does not update anything must be written to the binary log in SBR
+# and MIXED modes. We check this property by counting occurrences in t1 before and after
+# the insert and comparing the binlog positions. The count should be the same in both points
+# and the statement should be in the binary log.
+--connection master
+--let $binlog_file= query_get_value("SHOW MASTER STATUS", File, 1)
+--let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1)
+--let $statement_file=INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a
+--eval $statement_file
+
+--let $assert_cond= COUNT(*) = 6 FROM t1
+--let $assert_text= Count of elements in t1 should be 6.
+--source include/assert.inc
+
+if (`SELECT @@BINLOG_FORMAT = 'ROW'`)
+{
+ --let $binlog_position_cmp= =
+ --let $assert_cond= [SHOW MASTER STATUS, Position, 1] $binlog_position_cmp $binlog_start
+ --let $assert_text= In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.
+}
+if (`SELECT @@BINLOG_FORMAT != 'ROW'`)
+{
+ --let $assert_cond= \'[\'SHOW BINLOG EVENTS IN "$binlog_file" FROM $binlog_start LIMIT 2, 1\', Info, 1]\' LIKE \'%$statement_file\'
+ --let $assert_text= In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.
+}
+--source include/assert.inc
-# Compare results
-
-SELECT * FROM t1 ORDER BY a;
-
-sync_slave_with_master;
-SELECT * FROM t1 ORDER BY a;
-
-# Now do the same for MyISAM
-
-connection master;
-drop table t1;
-eval CREATE TABLE t1 (
- a int unsigned not null auto_increment primary key,
- b int unsigned,
- unique (b)
-) ENGINE=$engine_type2;
-
-INSERT INTO t1 VALUES (1, 1);
-INSERT INTO t1 VALUES (2, 2);
-INSERT INTO t1 VALUES (3, 3);
-INSERT INTO t1 VALUES (4, 4);
-
---disable_warnings
-INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
---enable_warnings
-
-SELECT * FROM t1 ORDER BY a;
-
-sync_slave_with_master;
-SELECT * FROM t1 ORDER BY a;
-
-connection master;
+# Clean up
+--connection master
drop table t1, t2;
-sync_slave_with_master;
-
-# End of 4.1 tests
+--sync_slave_with_master
=== modified file 'mysql-test/include/commit.inc'
--- a/mysql-test/include/commit.inc 2010-08-18 09:35:41 +0000
+++ b/mysql-test/include/commit.inc 2011-01-31 13:11:05 +0000
@@ -502,16 +502,16 @@ call p_verify_status_increment(2, 2, 2,
--echo # 12. Read-write statement: IODKU, change 0 rows.
--echo #
insert t1 set a=2 on duplicate key update a=2;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
commit;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
--echo # 13. Read-write statement: INSERT IGNORE, change 0 rows.
--echo #
insert ignore t1 set a=2;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
commit;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
--echo # 14. Read-write statement: INSERT IGNORE, change 1 row.
--echo #
=== modified file 'mysql-test/include/gis_keys.inc'
--- a/mysql-test/include/gis_keys.inc 2007-11-01 14:03:09 +0000
+++ b/mysql-test/include/gis_keys.inc 2011-02-02 13:17:48 +0000
@@ -44,3 +44,19 @@ SELECT COUNT(*) FROM t2 IGNORE INDEX(p)
DROP TABLE t1, t2;
--echo End of 5.0 tests
+
+
+--echo #
+--echo # Test for bug #58650 "Failing assertion: primary_key_no == -1 ||
+--echo # primary_key_no == 0".
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+--echo # The minimal test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a));
+drop table t1;
+--echo # The original test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)));
+create unique index a on t1(a);
+drop table t1;
=== modified file 'mysql-test/include/mtr_warnings.sql'
--- a/mysql-test/include/mtr_warnings.sql 2010-10-14 10:05:59 +0000
+++ b/mysql-test/include/mtr_warnings.sql 2011-02-02 11:54:49 +0000
@@ -183,9 +183,6 @@ INSERT INTO global_suppressions VALUES
("The slave I.O thread stops because a fatal error is encountered when it try to get the value of SERVER_ID variable from master."),
(".SELECT UNIX_TIMESTAMP... failed on master, do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS"),
- /* Test case for Bug#31590 in order_by.test produces the following error */
- ("Out of sort memory; increase server sort buffer size"),
-
/* Special case for Bug #26402 in show_check.test
- Question marks are not valid file name parts on Windows. Ignore
this error message.
=== modified file 'mysql-test/include/plugin.defs'
--- a/mysql-test/include/plugin.defs 2011-01-11 13:27:03 +0000
+++ b/mysql-test/include/plugin.defs 2011-01-31 15:32:57 +0000
@@ -27,7 +27,7 @@
# with name1, name2 etc from the comma separated list of plugin names
# in the optional 4th argument.
-auth_test_plugin plugin/auth PLUGIN_AUTH test_plugin_server
+auth_test_plugin plugin/auth PLUGIN_AUTH test_plugin_server,cleartext_plugin_server
qa_auth_interface plugin/auth PLUGIN_AUTH_INTERFACE qa_auth_interface
qa_auth_server plugin/auth PLUGIN_AUTH_SERVER qa_auth_server
qa_auth_client plugin/auth PLUGIN_AUTH_CLIENT qa_auth_client
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2011-01-29 21:53:17 +0000
+++ b/mysql-test/mysql-test-run.pl 2011-02-04 12:20:12 +0000
@@ -1884,9 +1884,12 @@ sub executable_setup () {
sub client_debug_arg($$) {
my ($args, $client_name)= @_;
+ # Workaround for Bug #50627: drop any debug opt
+ return if $client_name =~ /^mysqlbinlog/;
+
if ( $opt_debug ) {
mtr_add_arg($args,
- "--debug=$debug_d:t:A,%s/log/%s.trace",
+ "--loose-debug=$debug_d:t:A,%s/log/%s.trace",
$path_vardir_trace, $client_name)
}
}
=== modified file 'mysql-test/r/commit_1innodb.result'
--- a/mysql-test/r/commit_1innodb.result 2010-08-18 09:35:41 +0000
+++ b/mysql-test/r/commit_1innodb.result 2011-01-31 13:11:05 +0000
@@ -519,21 +519,21 @@ SUCCESS
# 12. Read-write statement: IODKU, change 0 rows.
#
insert t1 set a=2 on duplicate key update a=2;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
SUCCESS
commit;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
SUCCESS
# 13. Read-write statement: INSERT IGNORE, change 0 rows.
#
insert ignore t1 set a=2;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
SUCCESS
commit;
-call p_verify_status_increment(1, 0, 1, 0);
+call p_verify_status_increment(2, 2, 1, 0);
SUCCESS
# 14. Read-write statement: INSERT IGNORE, change 1 row.
=== modified file 'mysql-test/r/csv_not_null.result'
--- a/mysql-test/r/csv_not_null.result 2009-02-05 09:49:32 +0000
+++ b/mysql-test/r/csv_not_null.result 2011-01-25 06:44:28 +0000
@@ -19,13 +19,16 @@ INSERT INTO t1 VALUES();
SELECT * FROM t1;
a b c d e f
0 foo 0000-00-00
+INSERT INTO t1 VALUES(default,default,default,default,default,default);
SELECT * FROM t1;
a b c d e f
0 foo 0000-00-00
+0 foo 0000-00-00
INSERT INTO t1 VALUES(0,'abc','def','ghi','bar','1999-12-31');
SELECT * FROM t1;
a b c d e f
0 foo 0000-00-00
+0 foo 0000-00-00
0 abc def ghi bar 1999-12-31
# === insert failures ===
INSERT INTO t1 VALUES(NULL,'ab','a','b','foo','2007-01-01');
=== added file 'mysql-test/r/filesort_debug.result'
--- a/mysql-test/r/filesort_debug.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/filesort_debug.result 2011-02-02 11:54:49 +0000
@@ -0,0 +1,16 @@
+SET @old_debug= @@session.debug;
+#
+# Bug#36022 please log more information about "Sort aborted" queries
+#
+CREATE TABLE t1(f0 int auto_increment primary key, f1 int);
+INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5);
+SET session debug= '+d,make_char_array_fail';
+CALL mtr.add_suppression("Out of sort memory");
+SELECT * FROM t1 ORDER BY f1 ASC, f0;
+ERROR HY001: Out of sort memory, consider increasing server sort buffer size
+SET session debug= @old_debug;
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+DELETE FROM t1 ORDER BY (f1(10)) LIMIT 1;
+ERROR 42000: Incorrect number of arguments for FUNCTION test.f1; expected 0, got 1
+DROP TABLE t1;
+DROP FUNCTION f1;
=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result 2010-12-21 12:32:15 +0000
+++ b/mysql-test/r/func_group.result 2011-02-02 09:18:44 +0000
@@ -1739,6 +1739,16 @@ SELECT RELEASE_LOCK('aaaaaaaaaaaaaaaaa')
#
End of 5.1 tests
#
+# Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(),
+# file .\item_sum.cc, line 587
+#
+CREATE TABLE t1(a int, KEY(a));
+INSERT INTO t1 VALUES (1), (2);
+SELECT 1 FROM t1 ORDER BY AVG(DISTINCT a);
+1
+1
+DROP TABLE t1;
+#
# Bug#55648: Server crash on MIN/MAX on maximum time value
#
CREATE TABLE t1(c1 TIME NOT NULL);
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2010-12-17 11:11:34 +0000
+++ b/mysql-test/r/func_time.result 2011-02-02 18:16:06 +0000
@@ -1273,6 +1273,24 @@ date_add('1000-01-01 00:00:00', interval
select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond);
date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond)
1000-01-01 00:00:01.020000
+#
+# Bug #52315 part 2 : utc_date() crashes when system time > year 2037
+#
+SET TIMESTAMP=-147490000;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=2147483648;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=2147483646;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=2147483647;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=0;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=-1;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=1;
+SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=0;
End of 5.0 tests
select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND)
=== modified file 'mysql-test/r/gis.result'
--- a/mysql-test/r/gis.result 2011-01-12 13:11:31 +0000
+++ b/mysql-test/r/gis.result 2011-02-02 13:53:56 +0000
@@ -960,6 +960,18 @@ COUNT(*)
2
DROP TABLE t1, t2;
End of 5.0 tests
+#
+# Test for bug #58650 "Failing assertion: primary_key_no == -1 ||
+# primary_key_no == 0".
+#
+drop table if exists t1;
+# The minimal test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a));
+drop table t1;
+# The original test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)));
+create unique index a on t1(a);
+drop table t1;
create table `t1` (`col002` point)engine=myisam;
insert into t1 values (),(),();
select min(`col002`) from t1 union select `col002` from t1;
=== modified file 'mysql-test/r/join_outer.result'
--- a/mysql-test/r/join_outer.result 2011-01-13 08:33:30 +0000
+++ b/mysql-test/r/join_outer.result 2011-02-01 14:19:34 +0000
@@ -1502,4 +1502,146 @@ WHERE 7;
col_datetime_key
NULL
DROP TABLE BB;
+#
+# Bug#58490: Incorrect result in multi level OUTER JOIN
+# in combination with IS NULL
+#
+CREATE TABLE t1 (i INT NOT NULL);
+INSERT INTO t1 VALUES (0), (2),(3),(4);
+CREATE TABLE t2 (i INT NOT NULL);
+INSERT INTO t2 VALUES (0),(1), (3),(4);
+CREATE TABLE t3 (i INT NOT NULL);
+INSERT INTO t3 VALUES (0),(1),(2), (4);
+CREATE TABLE t4 (i INT NOT NULL);
+INSERT INTO t4 VALUES (0),(1),(2),(3) ;
+SELECT * FROM
+t1 LEFT JOIN
+( t2 LEFT JOIN
+( t3 LEFT JOIN
+t4
+ON t4.i = t3.i
+)
+ON t3.i = t2.i
+)
+ON t2.i = t1.i
+;
+i i i i
+0 0 0 0
+2 NULL NULL NULL
+3 3 NULL NULL
+4 4 4 NULL
+SELECT * FROM
+t1 LEFT JOIN
+( t2 LEFT JOIN
+( t3 LEFT JOIN
+t4
+ON t4.i = t3.i
+)
+ON t3.i = t2.i
+)
+ON t2.i = t1.i
+WHERE t4.i IS NULL;
+i i i i
+2 NULL NULL NULL
+3 3 NULL NULL
+4 4 4 NULL
+SELECT * FROM
+t1 LEFT JOIN
+( ( t2 LEFT JOIN
+t3
+ON t3.i = t2.i
+)
+)
+ON t2.i = t1.i
+WHERE t3.i IS NULL;
+i i i
+2 NULL NULL
+3 3 NULL
+SELECT * FROM
+t1 LEFT JOIN
+( ( t2 LEFT JOIN
+t3
+ON t3.i = t2.i
+)
+JOIN t4
+ON t4.i=t2.i
+)
+ON t2.i = t1.i
+WHERE t3.i IS NULL;
+i i i i
+2 NULL NULL NULL
+3 3 NULL 3
+4 NULL NULL NULL
+SELECT * FROM
+t1 LEFT JOIN
+( ( t2 LEFT JOIN
+t3
+ON t3.i = t2.i
+)
+JOIN (t4 AS t4a JOIN t4 AS t4b ON t4a.i=t4b.i)
+ON t4a.i=t2.i
+)
+ON t2.i = t1.i
+WHERE t3.i IS NULL;
+i i i i i
+2 NULL NULL NULL NULL
+3 3 NULL 3 3
+4 NULL NULL NULL NULL
+SELECT * FROM
+t1 LEFT JOIN
+( ( t2 LEFT JOIN
+t3
+ON t3.i = t2.i
+)
+JOIN (t4 AS t4a, t4 AS t4b)
+ON t4a.i=t2.i
+)
+ON t2.i = t1.i
+WHERE t3.i IS NULL;
+i i i i i
+2 NULL NULL NULL NULL
+3 3 NULL 3 0
+3 3 NULL 3 1
+3 3 NULL 3 2
+3 3 NULL 3 3
+4 NULL NULL NULL NULL
+DROP TABLE t1,t2,t3,t4;
+#
+# Bug#49322(Duplicate): Server is adding extra NULL row
+# on processing a WHERE clause
+#
+CREATE TABLE h (pk INT NOT NULL, col_int_key INT);
+INSERT INTO h VALUES (1,NULL),(4,2),(5,2),(3,4),(2,8);
+CREATE TABLE m (pk INT NOT NULL, col_int_key INT);
+INSERT INTO m VALUES (1,2),(2,7),(3,5),(4,7),(5,5),(6,NULL),(7,NULL),(8,9);
+CREATE TABLE k (pk INT NOT NULL, col_int_key INT);
+INSERT INTO k VALUES (1,9),(2,2),(3,5),(4,2),(5,7),(6,0),(7,5);
+SELECT TABLE1.pk FROM k TABLE1
+RIGHT JOIN h TABLE2 ON TABLE1.col_int_key=TABLE2.col_int_key
+RIGHT JOIN m TABLE4 ON TABLE2.col_int_key=TABLE4.col_int_key;
+pk
+2
+4
+2
+4
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+SELECT TABLE1.pk FROM k TABLE1
+RIGHT JOIN h TABLE2 ON TABLE1.col_int_key=TABLE2.col_int_key
+RIGHT JOIN m TABLE4 ON TABLE2.col_int_key=TABLE4.col_int_key
+WHERE TABLE1.pk IS NULL;
+pk
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+DROP TABLE h,m,k;
End of 5.1 tests
=== modified file 'mysql-test/r/not_embedded_server.result'
--- a/mysql-test/r/not_embedded_server.result 2011-01-07 12:08:05 +0000
+++ b/mysql-test/r/not_embedded_server.result 2011-02-04 04:59:55 +0000
@@ -3,6 +3,10 @@ SHOW VARIABLES like 'slave_skip_errors';
Variable_name Value
slave_skip_errors OFF
#
+# Bug#58026: massive recursion and crash in regular expression handling
+#
+SELECT '1' RLIKE RPAD('1', 10000, '(');
+#
# WL#4284: Transactional DDL locking
#
# FLUSH PRIVILEGES should not implicitly unlock locked tables.
=== modified file 'mysql-test/r/order_by.result'
--- a/mysql-test/r/order_by.result 2010-09-13 12:46:55 +0000
+++ b/mysql-test/r/order_by.result 2011-02-02 11:54:49 +0000
@@ -1425,8 +1425,9 @@ set session sort_buffer_size= 30000;
Warnings:
Warning 1292 Truncated incorrect sort_buffer_size value: '30000'
set session max_sort_length= 2180;
+CALL mtr.add_suppression("Out of sort memory");
select * from t1 order by b;
-ERROR HY001: Out of sort memory; increase server sort buffer size
+ERROR HY001: Out of sort memory, consider increasing server sort buffer size
drop table t1;
#
# Bug #39844: Query Crash Mysql Server 5.0.67
=== modified file 'mysql-test/r/plugin_auth.result'
--- a/mysql-test/r/plugin_auth.result 2011-01-16 03:59:05 +0000
+++ b/mysql-test/r/plugin_auth.result 2011-01-31 15:32:57 +0000
@@ -330,4 +330,16 @@ mysqld is alive
# Executing 'mysqldump'
# Executing 'mysql_upgrade'
The --upgrade-system-tables option was used, databases won't be touched.
+#
+# Bug #59657: Move the client authentication_pam plugin into the
+# server repository
+#
+CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server'
+ AS 'cleartext_test';
+## test plugin auth
+ERROR 28000: Access denied for user 'uplain'@'localhost' (using password: YES)
+select USER(),CURRENT_USER();
+USER() CURRENT_USER()
+uplain@localhost uplain@localhost
+DROP USER uplain@localhost;
End of 5.5 tests
=== modified file 'mysql-test/r/range.result'
--- a/mysql-test/r/range.result 2010-08-26 12:35:38 +0000
+++ b/mysql-test/r/range.result 2011-02-01 12:23:28 +0000
@@ -1666,4 +1666,105 @@ c_key c_notkey
1 1
3 3
DROP TABLE t1;
+#
+# Bug #57030: 'BETWEEN' evaluation is incorrect
+#
+CREATE TABLE t1(pk INT PRIMARY KEY, i4 INT);
+CREATE UNIQUE INDEX i4_uq ON t1(i4);
+INSERT INTO t1 VALUES (1,10), (2,20), (3,30);
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const i4_uq i4_uq 5 const 1
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 10;
+pk i4
+1 10
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND i4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const i4_uq i4_uq 5 const 1
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND i4;
+pk i4
+1 10
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 3 Using where
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
+pk i4
+1 10
+2 20
+3 30
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using where
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
+pk i4
+1 10
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND 10;
+pk i4
+1 10
+2 20
+3 30
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 11 AND 11;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+SELECT * FROM t1 WHERE 10 BETWEEN 11 AND 11;
+pk i4
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 100 AND 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+SELECT * FROM t1 WHERE 10 BETWEEN 100 AND 0;
+pk i4
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 100 AND 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1 WHERE i4 BETWEEN 100 AND 0;
+pk i4
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 2 Using where
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
+pk i4
+1 10
+2 20
+3 30
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 999999999999999 AND 30;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1 WHERE i4 BETWEEN 999999999999999 AND 30;
+pk i4
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using where
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
+pk i4
+1 10
+2 20
+EXPLAIN
+SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL i4_uq NULL NULL NULL 3
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using where
+SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
+pk i4 pk i4
+EXPLAIN
+SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL i4_uq NULL NULL NULL 3
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using where
+SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
+pk i4 pk i4
+DROP TABLE t1;
End of 5.1 tests
=== modified file 'mysql-test/r/symlink.result'
--- a/mysql-test/r/symlink.result 2010-04-01 14:49:02 +0000
+++ b/mysql-test/r/symlink.result 2011-01-31 09:34:39 +0000
@@ -22,7 +22,8 @@ insert into t1 (b) select b from t2;
insert into t2 (b) select b from t1;
insert into t1 (b) select b from t2;
drop table t2;
-create table t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="MYSQLTEST_VARDIR/tmp" index directory="MYSQLTEST_VARDIR/run";
+create table t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam data directory="MYSQLTEST_VARDIR/tmp" index directory="MYSQLTEST_VARDIR/run";
insert into t9 select * from t1;
check table t9;
Table Op Msg_type Msg_text
@@ -56,11 +57,17 @@ t9 CREATE TABLE `t9` (
PRIMARY KEY (`a`)
) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
create database mysqltest;
-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="/this-dir-does-not-exist";
Got one of the listed errors
-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="MYSQLTEST_VARDIR/run";
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="not-hard-path";
+ERROR 42000: Incorrect table name 'not-hard-path'
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="MYSQLTEST_VARDIR/run";
Got one of the listed errors
-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="MYSQLTEST_VARDIR/tmp";
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam data directory="MYSQLTEST_VARDIR/tmp";
Got one of the listed errors
alter table t9 rename mysqltest.t9;
select count(*) from mysqltest.t9;
=== added file 'mysql-test/suite/innodb/r/innodb_bug30423.result'
--- a/mysql-test/suite/innodb/r/innodb_bug30423.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_bug30423.result 2011-01-15 07:24:47 +0000
@@ -0,0 +1,95 @@
+set global innodb_stats_method = default;
+select @@innodb_stats_method;
+@@innodb_stats_method
+nulls_equal
+select count(*) from bug30243_3 where org_id is not NULL;
+count(*)
+20
+select count(*) from bug30243_3 where org_id is NULL;
+count(*)
+16384
+select count(*) from bug30243_2 where org_id is not NULL;
+count(*)
+224
+select count(*) from bug30243_2 where org_id is NULL;
+count(*)
+65536
+select @@innodb_stats_method;
+@@innodb_stats_method
+nulls_equal
+analyze table bug30243_1;
+Table Op Msg_type Msg_text
+test.bug30243_1 analyze status OK
+analyze table bug30243_2;
+Table Op Msg_type Msg_text
+test.bug30243_2 analyze status OK
+analyze table bug30243_3;
+Table Op Msg_type Msg_text
+test.bug30243_3 analyze status OK
+set global innodb_stats_method = "NULL";
+ERROR 42000: Variable 'innodb_stats_method' can't be set to the value of 'NULL'
+set global innodb_stats_method = "nulls_ignored";
+select @@innodb_stats_method;
+@@innodb_stats_method
+nulls_ignored
+analyze table bug30243_1;
+Table Op Msg_type Msg_text
+test.bug30243_1 analyze status OK
+analyze table bug30243_2;
+Table Op Msg_type Msg_text
+test.bug30243_2 analyze status OK
+analyze table bug30243_3;
+Table Op Msg_type Msg_text
+test.bug30243_3 analyze status OK
+explain SELECT COUNT(*), 0
+FROM bug30243_1 orgs
+LEFT JOIN bug30243_3 sa_opportunities
+ON orgs.org_id=sa_opportunities.org_id
+LEFT JOIN bug30243_2 contacts
+ON orgs.org_id=contacts.org_id ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE orgs index NULL org_id 4 NULL 128 Using index
+1 SIMPLE sa_opportunities ref org_id org_id 5 test.orgs.org_id 1 Using index
+1 SIMPLE contacts ref contacts$org_id contacts$org_id 5 test.orgs.org_id 1 Using index
+select @@innodb_stats_method;
+@@innodb_stats_method
+nulls_ignored
+set global innodb_stats_method = "nulls_unequal";
+select @@innodb_stats_method;
+@@innodb_stats_method
+nulls_unequal
+analyze table bug30243_1;
+Table Op Msg_type Msg_text
+test.bug30243_1 analyze status OK
+analyze table bug30243_2;
+Table Op Msg_type Msg_text
+test.bug30243_2 analyze status OK
+analyze table bug30243_3;
+Table Op Msg_type Msg_text
+test.bug30243_3 analyze status OK
+explain SELECT COUNT(*), 0
+FROM bug30243_1 orgs
+LEFT JOIN bug30243_3 sa_opportunities
+ON orgs.org_id=sa_opportunities.org_id
+LEFT JOIN bug30243_2 contacts
+ON orgs.org_id=contacts.org_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE orgs index NULL org_id 4 NULL 128 Using index
+1 SIMPLE sa_opportunities ref org_id org_id 5 test.orgs.org_id 1 Using index
+1 SIMPLE contacts ref contacts$org_id contacts$org_id 5 test.orgs.org_id 1 Using index
+SELECT COUNT(*) FROM table_bug30423 WHERE org_id IS NULL;
+COUNT(*)
+1024
+set global innodb_stats_method = "nulls_unequal";
+analyze table table_bug30423;
+Table Op Msg_type Msg_text
+test.table_bug30423 analyze status OK
+set global innodb_stats_method = "nulls_ignored";
+analyze table table_bug30423;
+Table Op Msg_type Msg_text
+test.table_bug30423 analyze status OK
+set global innodb_stats_method = nulls_equal;
+drop table bug30243_2;
+drop table bug30243_1;
+drop table bug30243_3;
+drop table table_bug30423;
=== modified file 'mysql-test/suite/innodb/r/innodb_gis.result'
--- a/mysql-test/suite/innodb/r/innodb_gis.result 2010-08-17 06:24:33 +0000
+++ b/mysql-test/suite/innodb/r/innodb_gis.result 2011-02-02 13:53:56 +0000
@@ -585,5 +585,17 @@ COUNT(*)
2
DROP TABLE t1, t2;
End of 5.0 tests
+#
+# Test for bug #58650 "Failing assertion: primary_key_no == -1 ||
+# primary_key_no == 0".
+#
+drop table if exists t1;
+# The minimal test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)), unique key a (a));
+drop table t1;
+# The original test case.
+create table t1 (a int not null, b linestring not null, unique key b (b(12)));
+create unique index a on t1(a);
+drop table t1;
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
ERROR HY000: The used table type doesn't support SPATIAL indexes
=== added file 'mysql-test/suite/innodb/t/innodb_bug30423.test'
--- a/mysql-test/suite/innodb/t/innodb_bug30423.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug30423.test 2011-01-14 17:02:28 +0000
@@ -0,0 +1,211 @@
+# Test for Bug #30423, InnoDBs treatment of NULL in index stats causes
+# bad "rows examined" estimates.
+# Implemented InnoDB system variable "innodb_stats_method" with
+# "nulls_equal" (default), "nulls_unequal", and "nulls_ignored" options.
+
+-- source include/have_innodb.inc
+
+let $innodb_stats_method_orig = `select @@innodb_stats_method`;
+
+# default setting for innodb_stats_method is "nulls_equal"
+set global innodb_stats_method = default;
+
+select @@innodb_stats_method;
+
+# create three tables, bug30243_1, bug30243_2 and bug30243_3.
+# The test scenario is adopted from original bug #30423 report.
+# table bug30243_1 and bug30243_3 have many NULL values
+
+-- disable_result_log
+-- disable_query_log
+
+DROP TABLE IF EXISTS bug30243_1;
+CREATE TABLE bug30243_1 (
+ org_id int(11) NOT NULL default '0',
+ UNIQUE KEY (org_id)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+LOCK TABLES bug30243_1 WRITE;
+INSERT INTO bug30243_1 VALUES (11),(15),(16),(17),(19),(20),(21),(23),(24),
+(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(37),(38),(40),(41),
+(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),
+(57),(58),(59),(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),
+(72),(73),(74),(75),(76),(77),(78),(79),(80),(81),(82),(83),(84),(85),(86),
+(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),(100),(101),
+(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),
+(115),(116),(117),(118),(119),(120),(121),(122),(123),(124),(125),(126),(127),
+(128),(129),(130),(131),(132),(133),(134),(135),(136),(137),(138),(139),(140),
+(141),(142),(143),(144),(145);
+UNLOCK TABLES;
+
+DROP TABLE IF EXISTS bug30243_3;
+CREATE TABLE bug30243_3 (
+ org_id int(11) default NULL,
+ KEY (org_id)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO bug30243_3 VALUES (NULL);
+
+begin;
+let $i=14;
+while ($i)
+{
+ INSERT INTO bug30243_3 SELECT NULL FROM bug30243_3;
+ dec $i;
+}
+
+INSERT INTO bug30243_3 VALUES (34),(34),(35),(56),(58),(62),(62),(64),(65),(66),(80),(135),(137),(138),(139),(140),(142),(143),(144),(145);
+commit;
+
+DROP TABLE IF EXISTS bug30243_2;
+CREATE TABLE bug30243_2 (
+ org_id int(11) default NULL,
+ KEY `contacts$org_id` (org_id)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO bug30243_2 VALUES (NULL);
+
+begin;
+let $i=16;
+while ($i)
+{
+ INSERT INTO bug30243_2 SELECT NULL FROM bug30243_2;
+ dec $i;
+}
+
+INSERT INTO bug30243_2 VALUES (11),(15),(16),(17),(20),(21),(23),(24),(25),
+(26),(27),(28),(29),(30),(31),(32),(33),(34),(37),(38),(40),(41),(42),(43),
+(44),(45),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),
+(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),
+(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),
+(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),
+(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),
+(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(46),(48),
+(48),(50),(51),(52),(52),(53),(54),(55),(57),(60),(61),(62),(62),(62),(62),
+(62),(63),(64),(64),(65),(66),(66),(67),(68),(69),(70),(71),(72),(73),(74),
+(75),(76),(77),(78),(79),(80),(80),(81),(82),(83),(84),(85),(86),(87),(88),
+(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),(100),(101),(102),
+(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),
+(115),(116),(117),(118),(119),(120),(121),(122),(123),(124),(125),(126),
+(127),(128),(129),(130),(131),(132),(133),(133),(135),(135),(135),(135),
+(136),(136),(138),(138),(139),(139),(139),(140),(141),(141),(142),(143),
+(143),(145),(145);
+commit;
+
+
+-- enable_result_log
+-- enable_query_log
+
+# check tables's value
+select count(*) from bug30243_3 where org_id is not NULL;
+select count(*) from bug30243_3 where org_id is NULL;
+
+select count(*) from bug30243_2 where org_id is not NULL;
+select count(*) from bug30243_2 where org_id is NULL;
+
+select @@innodb_stats_method;
+
+analyze table bug30243_1;
+analyze table bug30243_2;
+analyze table bug30243_3;
+
+# Following query plan shows that we over estimate the rows per
+# unique value (since there are many NULLs).
+# Skip this query log since the stats estimate could vary from runs
+-- disable_query_log
+-- disable_result_log
+explain SELECT COUNT(*), 0
+ FROM bug30243_1 orgs
+ LEFT JOIN bug30243_3 sa_opportunities
+ ON orgs.org_id=sa_opportunities.org_id
+ LEFT JOIN bug30243_2 contacts
+ ON orgs.org_id=contacts.org_id ;
+-- enable_query_log
+-- enable_result_log
+
+# following set operation will fail
+#--error ER_WRONG_VALUE_FOR_VAR
+--error 1231
+set global innodb_stats_method = "NULL";
+
+set global innodb_stats_method = "nulls_ignored";
+
+select @@innodb_stats_method;
+
+# Regenerate the stats with "nulls_ignored" option
+
+analyze table bug30243_1;
+analyze table bug30243_2;
+analyze table bug30243_3;
+
+# Following query plan shows that we get the correct rows per
+# unique value (should be approximately 1 row per value)
+explain SELECT COUNT(*), 0
+ FROM bug30243_1 orgs
+ LEFT JOIN bug30243_3 sa_opportunities
+ ON orgs.org_id=sa_opportunities.org_id
+ LEFT JOIN bug30243_2 contacts
+ ON orgs.org_id=contacts.org_id ;
+
+select @@innodb_stats_method;
+
+# Try the "nulls_unequal" option
+set global innodb_stats_method = "nulls_unequal";
+
+select @@innodb_stats_method;
+
+analyze table bug30243_1;
+analyze table bug30243_2;
+analyze table bug30243_3;
+
+# Following query plan shows that we get the correct rows per
+# unique value (~1)
+explain SELECT COUNT(*), 0
+ FROM bug30243_1 orgs
+ LEFT JOIN bug30243_3 sa_opportunities
+ ON orgs.org_id=sa_opportunities.org_id
+ LEFT JOIN bug30243_2 contacts
+ ON orgs.org_id=contacts.org_id;
+
+
+# Create a table with all NULL values, make sure the stats calculation
+# does not crash with table of all NULL values
+-- disable_query_log
+CREATE TABLE table_bug30423 (
+ org_id int(11) default NULL,
+ KEY(org_id)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO `table_bug30423` VALUES (NULL);
+
+begin;
+let $i=10;
+while ($i)
+{
+ INSERT INTO table_bug30423 SELECT NULL FROM table_bug30423;
+ dec $i;
+}
+commit;
+
+-- enable_query_log
+
+SELECT COUNT(*) FROM table_bug30423 WHERE org_id IS NULL;
+
+# calculate the statistics for the table for "nulls_ignored" and
+# "nulls_unequal" option
+set global innodb_stats_method = "nulls_unequal";
+analyze table table_bug30423;
+
+set global innodb_stats_method = "nulls_ignored";
+analyze table table_bug30423;
+
+
+eval set global innodb_stats_method = $innodb_stats_method_orig;
+
+drop table bug30243_2;
+
+drop table bug30243_1;
+
+drop table bug30243_3;
+
+drop table table_bug30423;
=== modified file 'mysql-test/suite/innodb/t/innodb_bug56143.test'
--- a/mysql-test/suite/innodb/t/innodb_bug56143.test 2010-10-14 11:39:42 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug56143.test 2011-01-12 15:59:45 +0000
@@ -8,6 +8,11 @@
-- disable_query_log
-- disable_result_log
+if ($VALGRIND_TEST)
+{
+ call mtr.add_suppression("InnoDB: Warning: a long semaphore wait:");
+}
+
SET foreign_key_checks=0;
DROP TABLE IF EXISTS bug56143_1;
=== added file 'mysql-test/suite/rpl/r/rpl_insert_duplicate.result'
--- a/mysql-test/suite/rpl/r/rpl_insert_duplicate.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_insert_duplicate.result 2011-01-28 12:09:15 +0000
@@ -0,0 +1,29 @@
+include/master-slave.inc
+[connection master]
+CREATE TABLE t1 (
+a INT UNSIGNED NOT NULL PRIMARY KEY
+) ENGINE=innodb;
+CREATE TABLE t2 (
+a INT UNSIGNED
+) ENGINE=innodb;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 SELECT t2.a FROM t2 ORDER BY t2.a ON DUPLICATE KEY UPDATE t1.a= t1.a;
+include/assert.inc [Sum of elements in t1 should be 1.]
+include/assert.inc [In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.]
+include/diff_tables.inc [master:test.t1 , slave:test.t1]
+drop table t1, t2;
+CREATE TABLE t1 (
+a INT UNSIGNED NOT NULL PRIMARY KEY
+) ENGINE=myisam;
+CREATE TABLE t2 (
+a INT UNSIGNED
+) ENGINE=myisam;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t1 SELECT t2.a FROM t2 ORDER BY t2.a ON DUPLICATE KEY UPDATE t1.a= t1.a;
+include/assert.inc [Sum of elements in t1 should be 1.]
+include/assert.inc [In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.]
+include/diff_tables.inc [master:test.t1 , slave:test.t1]
+drop table t1, t2;
+include/rpl_end.inc
=== modified file 'mysql-test/suite/rpl/r/rpl_insert_ignore.result'
--- a/mysql-test/suite/rpl/r/rpl_insert_ignore.result 2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/r/rpl_insert_ignore.result 2011-01-31 14:34:04 +0000
@@ -21,48 +21,36 @@ INSERT INTO t2 VALUES (4, 3);
INSERT INTO t2 VALUES (5, 4);
INSERT INTO t2 VALUES (6, 6);
INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
-SELECT * FROM t1 ORDER BY a;
-a b
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
-SELECT * FROM t1 ORDER BY a;
-a b
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
-drop table t1;
+include/assert.inc [Count of elements in t1 should be 6.]
+include/diff_tables.inc [master:test.t1 , slave:test.t1]
+INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
+include/assert.inc [Count of elements in t1 should be 6.]
+include/assert.inc [In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.]
+drop table t1, t2;
CREATE TABLE t1 (
a int unsigned not null auto_increment primary key,
b int unsigned,
unique (b)
) ENGINE=myisam;
-INSERT INTO t1 VALUES (1, 1);
-INSERT INTO t1 VALUES (2, 2);
-INSERT INTO t1 VALUES (3, 3);
-INSERT INTO t1 VALUES (4, 4);
+CREATE TABLE t2 (
+a int unsigned, # to force INSERT SELECT to have a certain order
+b int unsigned
+) ENGINE=myisam;
+INSERT INTO t1 VALUES (NULL, 1);
+INSERT INTO t1 VALUES (NULL, 2);
+INSERT INTO t1 VALUES (NULL, 3);
+INSERT INTO t1 VALUES (NULL, 4);
+INSERT INTO t2 VALUES (1, 1);
+INSERT INTO t2 VALUES (2, 2);
+INSERT INTO t2 VALUES (3, 5);
+INSERT INTO t2 VALUES (4, 3);
+INSERT INTO t2 VALUES (5, 4);
+INSERT INTO t2 VALUES (6, 6);
+INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
+include/assert.inc [Count of elements in t1 should be 6.]
+include/diff_tables.inc [master:test.t1 , slave:test.t1]
INSERT IGNORE INTO t1 SELECT NULL, t2.b FROM t2 ORDER BY t2.a;
-SELECT * FROM t1 ORDER BY a;
-a b
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
-SELECT * FROM t1 ORDER BY a;
-a b
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
+include/assert.inc [Count of elements in t1 should be 6.]
+include/assert.inc [In SBR or MIXED modes, the event in the binlog should be the same that was executed. In RBR mode, binlog position should stay unchanged.]
drop table t1, t2;
include/rpl_end.inc
=== modified file 'mysql-test/suite/rpl/r/rpl_log_pos.result'
--- a/mysql-test/suite/rpl/r/rpl_log_pos.result 2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/r/rpl_log_pos.result 2011-01-31 13:11:05 +0000
@@ -9,7 +9,7 @@ change master to master_log_pos=MASTER_L
Read_Master_Log_Pos = '75'
start slave;
include/wait_for_slave_io_error.inc [errno=1236]
-Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event''
+Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master''
include/stop_slave_sql.inc
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
=== modified file 'mysql-test/suite/rpl/t/disabled.def'
--- a/mysql-test/suite/rpl/t/disabled.def 2011-01-26 12:44:09 +0000
+++ b/mysql-test/suite/rpl/t/disabled.def 2011-01-31 13:11:05 +0000
@@ -14,7 +14,6 @@ rpl_failed_optimize : WL#4284: Can
rpl_read_only : WL#4284: Setting Read only won't succeed until all metadata locks are released.
rpl_row_create_table : Bug#51574 2010-02-27 andrei failed different way than earlier with bug#45576
rpl_spec_variables : BUG#47661 2009-10-27 jasonh rpl_spec_variables fails on PB2 hpux
-rpl_log_pos : BUG#55675 2010-09-10 alfranio rpl.rpl_log_pos fails sporadically with error binlog truncated in the middle
rpl_get_master_version_and_clock : Bug#59178 Jan 05 2011 joro Valgrind warnings rpl_get_master_version_and_clock
rpl_row_until : BUG#59543 Jan 26 2011 alfranio Replication test from eits suite rpl_row_until times out
rpl_stm_until : BUG#59543 Jan 26 2011 alfranio Replication test from eits suite rpl_row_until times out
=== added file 'mysql-test/suite/rpl/t/rpl_insert_duplicate.test'
--- a/mysql-test/suite/rpl/t/rpl_insert_duplicate.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_insert_duplicate.test 2011-01-28 12:09:15 +0000
@@ -0,0 +1,14 @@
+#########################################
+# Wrapper for rpl_insert_duplicate.test #
+#########################################
+-- source include/master-slave.inc
+-- source include/have_innodb.inc
+#-- source include/have_binlog_format_mixed_or_statement.inc
+
+let $engine_type=innodb;
+-- source extra/rpl_tests/rpl_insert_duplicate.test
+
+let $engine_type=myisam;
+-- source extra/rpl_tests/rpl_insert_duplicate.test
+
+--source include/rpl_end.inc
=== modified file 'mysql-test/suite/rpl/t/rpl_insert_ignore.test'
--- a/mysql-test/suite/rpl/t/rpl_insert_ignore.test 2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/t/rpl_insert_ignore.test 2011-01-31 14:34:04 +0000
@@ -7,7 +7,10 @@
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
-let $engine_type=innodb;
-let $engine_type2=myisam;
+-- let $engine_type=innodb
-- source extra/rpl_tests/rpl_insert_ignore.test
+
+-- let $engine_type=myisam
+-- source extra/rpl_tests/rpl_insert_ignore.test
+
--source include/rpl_end.inc
=== modified file 'mysql-test/suite/sys_vars/r/all_vars.result'
--- a/mysql-test/suite/sys_vars/r/all_vars.result 2010-10-21 08:30:43 +0000
+++ b/mysql-test/suite/sys_vars/r/all_vars.result 2011-01-15 07:24:47 +0000
@@ -11,7 +11,9 @@ There should be *no* long test name list
select variable_name as `There should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null;
There should be *no* variables listed below:
+INNODB_STATS_METHOD
INNODB_FILE_FORMAT_MAX
+INNODB_STATS_METHOD
INNODB_FILE_FORMAT_MAX
drop table t1;
drop table t2;
=== modified file 'mysql-test/t/csv_not_null.test'
--- a/mysql-test/t/csv_not_null.test 2009-02-05 09:49:32 +0000
+++ b/mysql-test/t/csv_not_null.test 2011-01-25 06:44:28 +0000
@@ -55,10 +55,8 @@ INSERT INTO t1 VALUES();
SELECT * FROM t1;
-- disable_warnings
-# NOTE - Test disabled due to enum crash for this INSERT
-# See Bug#33717 - INSERT...(default) fails for enum.
-# Crashes CSV tables, loads spaces for MyISAM
-#INSERT INTO t1 VALUES(default,default,default,default,default,default);
+# Bug#33717 - INSERT...(default) fails for enum.
+INSERT INTO t1 VALUES(default,default,default,default,default,default);
-- enable_warnings
SELECT * FROM t1;
=== added file 'mysql-test/t/filesort_debug.test'
--- a/mysql-test/t/filesort_debug.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/filesort_debug.test 2011-02-02 11:54:49 +0000
@@ -0,0 +1,23 @@
+--source include/have_debug.inc
+
+SET @old_debug= @@session.debug;
+
+--echo #
+--echo # Bug#36022 please log more information about "Sort aborted" queries
+--echo #
+
+CREATE TABLE t1(f0 int auto_increment primary key, f1 int);
+INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5);
+
+SET session debug= '+d,make_char_array_fail';
+CALL mtr.add_suppression("Out of sort memory");
+--error ER_OUT_OF_SORTMEMORY
+SELECT * FROM t1 ORDER BY f1 ASC, f0;
+SET session debug= @old_debug;
+
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+--error ER_SP_WRONG_NO_OF_ARGS
+DELETE FROM t1 ORDER BY (f1(10)) LIMIT 1;
+
+DROP TABLE t1;
+DROP FUNCTION f1;
=== modified file 'mysql-test/t/func_group.test'
--- a/mysql-test/t/func_group.test 2010-12-21 12:32:15 +0000
+++ b/mysql-test/t/func_group.test 2011-02-02 09:18:44 +0000
@@ -1120,6 +1120,17 @@ SELECT RELEASE_LOCK('aaaaaaaaaaaaaaaaa')
--echo #
--echo End of 5.1 tests
+###
+--echo #
+--echo # Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(),
+--echo # file .\item_sum.cc, line 587
+--echo #
+
+CREATE TABLE t1(a int, KEY(a));
+INSERT INTO t1 VALUES (1), (2);
+SELECT 1 FROM t1 ORDER BY AVG(DISTINCT a);
+DROP TABLE t1;
+
--echo #
--echo # Bug#55648: Server crash on MIN/MAX on maximum time value
--echo #
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2010-12-17 11:11:34 +0000
+++ b/mysql-test/t/func_time.test 2011-02-02 18:16:06 +0000
@@ -802,6 +802,26 @@ select LAST_DAY('2007-12-06 08:59:19.05'
select date_add('1000-01-01 00:00:00', interval '1.03:02:01.05' day_microsecond);
select date_add('1000-01-01 00:00:00', interval '1.02' day_microsecond);
+
+--echo #
+--echo # Bug #52315 part 2 : utc_date() crashes when system time > year 2037
+--echo #
+
+--disable_result_log
+SET TIMESTAMP=-147490000; SELECT UTC_TIMESTAMP();
+--error ER_WRONG_VALUE_FOR_VAR
+SET TIMESTAMP=2147483648; SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=2147483646; SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=2147483647; SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=0; SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=-1; SELECT UTC_TIMESTAMP();
+SET TIMESTAMP=1; SELECT UTC_TIMESTAMP();
+--enable_result_log
+
+#reset back the timestamp value
+SET TIMESTAMP=0;
+
+
--echo End of 5.0 tests
#
=== modified file 'mysql-test/t/join_outer.test'
--- a/mysql-test/t/join_outer.test 2011-01-13 08:33:30 +0000
+++ b/mysql-test/t/join_outer.test 2011-02-01 14:19:34 +0000
@@ -1092,4 +1092,128 @@ FROM BB table1 RIGHT JOIN BB table2
DROP TABLE BB;
+
+--echo #
+--echo # Bug#58490: Incorrect result in multi level OUTER JOIN
+--echo # in combination with IS NULL
+--echo #
+
+CREATE TABLE t1 (i INT NOT NULL);
+INSERT INTO t1 VALUES (0), (2),(3),(4);
+CREATE TABLE t2 (i INT NOT NULL);
+INSERT INTO t2 VALUES (0),(1), (3),(4);
+CREATE TABLE t3 (i INT NOT NULL);
+INSERT INTO t3 VALUES (0),(1),(2), (4);
+CREATE TABLE t4 (i INT NOT NULL);
+INSERT INTO t4 VALUES (0),(1),(2),(3) ;
+
+SELECT * FROM
+ t1 LEFT JOIN
+ ( t2 LEFT JOIN
+ ( t3 LEFT JOIN
+ t4
+ ON t4.i = t3.i
+ )
+ ON t3.i = t2.i
+ )
+ ON t2.i = t1.i
+ ;
+
+SELECT * FROM
+ t1 LEFT JOIN
+ ( t2 LEFT JOIN
+ ( t3 LEFT JOIN
+ t4
+ ON t4.i = t3.i
+ )
+ ON t3.i = t2.i
+ )
+ ON t2.i = t1.i
+ WHERE t4.i IS NULL;
+
+
+# Most simplified testcase to reproduce the bug.
+# (Has to be at least a two level nested outer join)
+SELECT * FROM
+ t1 LEFT JOIN
+ ( ( t2 LEFT JOIN
+ t3
+ ON t3.i = t2.i
+ )
+ )
+ ON t2.i = t1.i
+ WHERE t3.i IS NULL;
+
+
+# Extended testing:
+# We then add some equi-join inside the query above:
+# (There Used to be some problems here with first
+# proposed patch for this bug)
+SELECT * FROM
+ t1 LEFT JOIN
+ ( ( t2 LEFT JOIN
+ t3
+ ON t3.i = t2.i
+ )
+ JOIN t4
+ ON t4.i=t2.i
+ )
+ ON t2.i = t1.i
+ WHERE t3.i IS NULL;
+
+SELECT * FROM
+ t1 LEFT JOIN
+ ( ( t2 LEFT JOIN
+ t3
+ ON t3.i = t2.i
+ )
+ JOIN (t4 AS t4a JOIN t4 AS t4b ON t4a.i=t4b.i)
+ ON t4a.i=t2.i
+ )
+ ON t2.i = t1.i
+ WHERE t3.i IS NULL;
+
+SELECT * FROM
+ t1 LEFT JOIN
+ ( ( t2 LEFT JOIN
+ t3
+ ON t3.i = t2.i
+ )
+ JOIN (t4 AS t4a, t4 AS t4b)
+ ON t4a.i=t2.i
+ )
+ ON t2.i = t1.i
+ WHERE t3.i IS NULL;
+
+
+DROP TABLE t1,t2,t3,t4;
+
+## Bug#49322 & bug#58490 are duplicates. However, we include testcases
+## for both.
+--echo #
+--echo # Bug#49322(Duplicate): Server is adding extra NULL row
+--echo # on processing a WHERE clause
+--echo #
+
+CREATE TABLE h (pk INT NOT NULL, col_int_key INT);
+INSERT INTO h VALUES (1,NULL),(4,2),(5,2),(3,4),(2,8);
+
+CREATE TABLE m (pk INT NOT NULL, col_int_key INT);
+INSERT INTO m VALUES (1,2),(2,7),(3,5),(4,7),(5,5),(6,NULL),(7,NULL),(8,9);
+CREATE TABLE k (pk INT NOT NULL, col_int_key INT);
+INSERT INTO k VALUES (1,9),(2,2),(3,5),(4,2),(5,7),(6,0),(7,5);
+
+# Baseline query wo/ 'WHERE ... IS NULL' - was correct
+SELECT TABLE1.pk FROM k TABLE1
+RIGHT JOIN h TABLE2 ON TABLE1.col_int_key=TABLE2.col_int_key
+RIGHT JOIN m TABLE4 ON TABLE2.col_int_key=TABLE4.col_int_key;
+
+# Adding 'WHERE ... IS NULL' -> incorrect result
+SELECT TABLE1.pk FROM k TABLE1
+RIGHT JOIN h TABLE2 ON TABLE1.col_int_key=TABLE2.col_int_key
+RIGHT JOIN m TABLE4 ON TABLE2.col_int_key=TABLE4.col_int_key
+WHERE TABLE1.pk IS NULL;
+
+DROP TABLE h,m,k;
+
--echo End of 5.1 tests
=== modified file 'mysql-test/t/not_embedded_server.test'
--- a/mysql-test/t/not_embedded_server.test 2011-01-07 12:08:05 +0000
+++ b/mysql-test/t/not_embedded_server.test 2011-02-04 04:59:55 +0000
@@ -14,6 +14,16 @@ call mtr.add_suppression("Can't open and
SHOW VARIABLES like 'slave_skip_errors';
+--echo #
+--echo # Bug#58026: massive recursion and crash in regular expression handling
+--echo #
+
+--disable_result_log
+--error ER_STACK_OVERRUN_NEED_MORE
+SELECT '1' RLIKE RPAD('1', 10000, '(');
+--enable_result_log
+
+
# End of 5.1 tests
--echo #
=== modified file 'mysql-test/t/order_by.test'
--- a/mysql-test/t/order_by.test 2010-09-13 12:46:55 +0000
+++ b/mysql-test/t/order_by.test 2011-02-02 11:54:49 +0000
@@ -843,7 +843,8 @@ create table t1(a int, b tinytext);
insert into t1 values (1,2),(3,2);
set session sort_buffer_size= 30000;
set session max_sort_length= 2180;
---error 1038
+CALL mtr.add_suppression("Out of sort memory");
+--error ER_OUT_OF_SORTMEMORY
select * from t1 order by b;
drop table t1;
=== modified file 'mysql-test/t/plugin_auth.test'
--- a/mysql-test/t/plugin_auth.test 2011-01-16 03:59:05 +0000
+++ b/mysql-test/t/plugin_auth.test 2011-01-31 15:32:57 +0000
@@ -411,4 +411,26 @@ FLUSH PRIVILEGES;
--echo # Executing 'mysql_upgrade'
--exec $MYSQL_UPGRADE -u root -S $MASTER_MYSOCK -P $MASTER_MYPORT --default-auth=auth_test_plugin $PLUGIN_AUTH_OPT --skip-verbose --force --upgrade-system-tables
+--echo #
+--echo # Bug #59657: Move the client authentication_pam plugin into the
+--echo # server repository
+--echo #
+
+CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server'
+ AS 'cleartext_test';
+
+--echo ## test plugin auth
+--disable_query_log
+--error ER_ACCESS_DENIED_ERROR : this should fail : no grant
+connect(cleartext_fail_con,localhost,uplain,cleartext_test2);
+--enable_query_log
+
+connect(cleartext_con,localhost,uplain,cleartext_test);
+connection cleartext_con;
+select USER(),CURRENT_USER();
+
+connection default;
+disconnect cleartext_con;
+DROP USER uplain@localhost;
+
--echo End of 5.5 tests
=== modified file 'mysql-test/t/range.test'
--- a/mysql-test/t/range.test 2010-08-24 15:51:32 +0000
+++ b/mysql-test/t/range.test 2011-02-01 12:20:16 +0000
@@ -1325,4 +1325,71 @@ SELECT * FROM t1 WHERE 2 NOT BETWEEN c_n
DROP TABLE t1;
+--echo #
+--echo # Bug #57030: 'BETWEEN' evaluation is incorrect
+--echo #
+
+# Test some BETWEEN predicates which does *not* follow the
+# 'normal' pattern of <field> BETWEEN <low const> AND <high const>
+
+CREATE TABLE t1(pk INT PRIMARY KEY, i4 INT);
+CREATE UNIQUE INDEX i4_uq ON t1(i4);
+
+INSERT INTO t1 VALUES (1,10), (2,20), (3,30);
+
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 10;
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 10;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND i4;
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND i4;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
+SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND 10;
+SELECT * FROM t1 WHERE 10 BETWEEN 10 AND 10;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 11 AND 11;
+SELECT * FROM t1 WHERE 10 BETWEEN 11 AND 11;
+
+EXPLAIN
+SELECT * FROM t1 WHERE 10 BETWEEN 100 AND 0;
+SELECT * FROM t1 WHERE 10 BETWEEN 100 AND 0;
+
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 100 AND 0;
+SELECT * FROM t1 WHERE i4 BETWEEN 100 AND 0;
+
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
+
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 999999999999999 AND 30;
+SELECT * FROM t1 WHERE i4 BETWEEN 999999999999999 AND 30;
+
+EXPLAIN
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
+SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
+
+#Should detect the EQ_REF 't2.pk=t1.i4'
+EXPLAIN
+SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
+SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
+
+EXPLAIN
+SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
+SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
+
+DROP TABLE t1;
+
--echo End of 5.1 tests
=== modified file 'mysql-test/t/symlink.test'
--- a/mysql-test/t/symlink.test 2010-04-01 14:49:02 +0000
+++ b/mysql-test/t/symlink.test 2011-01-31 09:34:39 +0000
@@ -39,7 +39,8 @@ drop table t2;
#
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-eval create table t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" index directory="$MYSQLTEST_VARDIR/run";
+eval create table t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" index directory="$MYSQLTEST_VARDIR/run";
insert into t9 select * from t1;
check table t9;
@@ -71,21 +72,25 @@ SHOW CREATE TABLE t9;
create database mysqltest;
--error 1,1
-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="/this-dir-does-not-exist";
# temporarily disabled as it returns different result in the embedded server
-# --error ER_WRONG_ARGUMENTS, ER_WRONG_ARGUMENTS
-# create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
+--error ER_WRONG_TABLE_NAME
+create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="not-hard-path";
# Should fail becasue the file t9.MYI already exist in 'run'
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1,1,ER_UNKNOWN_ERROR
-eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="$MYSQLTEST_VARDIR/run";
+eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam index directory="$MYSQLTEST_VARDIR/run";
# Should fail becasue the file t9.MYD already exist in 'tmp'
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1,1
-eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp";
+eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a))
+engine=myisam data directory="$MYSQLTEST_VARDIR/tmp";
# Check moving table t9 from default database to mysqltest;
# In this case the symlinks should be removed.
=== modified file 'mysql-test/t/variables.test'
--- a/mysql-test/t/variables.test 2010-11-25 03:50:16 +0000
+++ b/mysql-test/t/variables.test 2011-02-02 18:13:28 +0000
@@ -779,7 +779,7 @@ SET @@myisam_mmap_size= 500M;
--echo # Bug #52315: utc_date() crashes when system time > year 2037
--echo #
---error 0, ER_UNKNOWN_ERROR
+--error 0, ER_WRONG_VALUE_FOR_VAR
SET TIMESTAMP=2*1024*1024*1024;
--echo #Should not crash
--disable_result_log
=== modified file 'plugin/auth/test_plugin.c'
--- a/plugin/auth/test_plugin.c 2010-10-27 15:12:17 +0000
+++ b/plugin/auth/test_plugin.c 2011-01-31 15:32:57 +0000
@@ -82,6 +82,36 @@ static struct st_mysql_auth auth_test_ha
auth_test_plugin
};
+/**
+ dialog test plugin mimicking the ordinary auth mechanism. Used to test the clear text plugin API
+*/
+static int auth_cleartext_plugin(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len;
+
+ /* read the password */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used= PASSWORD_USED_YES;
+
+ /* fail if the password is wrong */
+ if (strcmp((const char *) pkt, info->auth_string))
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+
+static struct st_mysql_auth auth_cleartext_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "mysql_clear_password", /* requires the clear text plugin */
+ auth_cleartext_plugin
+};
+
mysql_declare_plugin(test_plugin)
{
MYSQL_AUTHENTICATION_PLUGIN,
@@ -96,9 +126,24 @@ mysql_declare_plugin(test_plugin)
NULL,
NULL,
NULL
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &auth_cleartext_handler,
+ "cleartext_plugin_server",
+ "Georgi Kodinov",
+ "cleartext plugin API test plugin",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
}
mysql_declare_plugin_end;
+
/********************* CLIENT SIDE ***************************************/
/*
client plugin used for testing the plugin API
=== modified file 'regex/my_regex.h'
--- a/regex/my_regex.h 2005-09-29 00:08:24 +0000
+++ b/regex/my_regex.h 2011-02-04 04:47:46 +0000
@@ -28,6 +28,7 @@ typedef struct {
/* === regcomp.c === */
+typedef int (*my_regex_stack_check_t)();
extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset);
#define REG_BASIC 0000
#define REG_EXTENDED 0001
@@ -76,7 +77,8 @@ extern void my_regfree(my_regex_t *);
/* === reginit.c === */
-extern void my_regex_init(CHARSET_INFO *cs); /* Should be called for multithread progs */
+/* Should be called for multithread progs */
+extern void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func);
extern void my_regex_end(void); /* If one wants a clean end */
#ifdef __cplusplus
=== modified file 'regex/regcomp.c'
--- a/regex/regcomp.c 2010-07-23 20:16:29 +0000
+++ b/regex/regcomp.c 2011-02-04 04:59:55 +0000
@@ -31,6 +31,9 @@ struct parse {
CHARSET_INFO *charset; /* for ctype things */
};
+/* Check if there is enough stack space for recursion. */
+my_regex_stack_check_t my_regex_enough_mem_in_stack= NULL;
+
#include "regcomp.ih"
static char nuls[10]; /* place to point scanner in event of error */
@@ -117,7 +120,7 @@ CHARSET_INFO *charset;
# define GOODFLAGS(f) ((f)&~REG_DUMP)
#endif
- my_regex_init(charset); /* Init cclass if neaded */
+ my_regex_init(charset, NULL); /* Init cclass if neaded */
preg->charset=charset;
cflags = GOODFLAGS(cflags);
if ((cflags®_EXTENDED) && (cflags®_NOSPEC))
@@ -222,7 +225,15 @@ int stop; /* character this ERE should
/* do a bunch of concatenated expressions */
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
- p_ere_exp(p);
+ {
+ if (my_regex_enough_mem_in_stack &&
+ my_regex_enough_mem_in_stack())
+ {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ p_ere_exp(p);
+ }
if(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */
if (!EAT('|'))
=== modified file 'regex/reginit.c'
--- a/regex/reginit.c 2008-02-18 22:29:39 +0000
+++ b/regex/reginit.c 2011-02-04 04:47:46 +0000
@@ -4,10 +4,12 @@
#include <m_ctype.h>
#include <m_string.h>
#include "cclass.h"
+#include "my_regex.h"
static my_bool regex_inited=0;
+extern my_regex_stack_check_t my_regex_enough_mem_in_stack;
-void my_regex_init(CHARSET_INFO *cs)
+void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func)
{
char buff[CCLASS_LAST][256];
int count[CCLASS_LAST];
@@ -16,6 +18,7 @@ void my_regex_init(CHARSET_INFO *cs)
if (!regex_inited)
{
regex_inited=1;
+ my_regex_enough_mem_in_stack= func;
bzero((uchar*) &count,sizeof(count));
for (i=1 ; i<= 255; i++)
@@ -74,6 +77,7 @@ void my_regex_end()
int i;
for (i=0; i < CCLASS_LAST ; i++)
free((char*) cclasses[i].chars);
+ my_regex_enough_mem_in_stack= NULL;
regex_inited=0;
}
}
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2011-01-17 07:44:37 +0000
+++ b/sql-common/client.c 2011-01-31 15:32:57 +0000
@@ -2261,6 +2261,7 @@ typedef struct st_mysql_client_plugin_AU
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static auth_plugin_t native_password_client_plugin=
{
@@ -2294,10 +2295,27 @@ static auth_plugin_t old_password_client
old_password_auth_client
};
+static auth_plugin_t clear_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "mysql_clear_password",
+ "Georgi Kodinov",
+ "Clear password authentication plugin",
+ {0,1,0},
+ "GPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ clear_password_auth_client
+};
+
struct st_mysql_client_plugin *mysql_client_builtins[]=
{
(struct st_mysql_client_plugin *)&native_password_client_plugin,
(struct st_mysql_client_plugin *)&old_password_client_plugin,
+ (struct st_mysql_client_plugin *)&clear_password_client_plugin,
0
};
@@ -4271,3 +4289,20 @@ static int old_password_auth_client(MYSQ
DBUG_RETURN(CR_OK);
}
+
+/**
+ The main function of the mysql_clear_password authentication plugin.
+*/
+
+static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int res;
+
+ /* send password in clear text */
+ res= vio->write_packet(vio, (const unsigned char *) mysql->passwd,
+ strlen(mysql->passwd) + 1);
+
+ return res ? CR_ERROR : CR_OK;
+}
+
+
=== modified file 'sql-common/my_time.c'
--- a/sql-common/my_time.c 2010-11-04 13:18:27 +0000
+++ b/sql-common/my_time.c 2011-02-02 18:13:28 +0000
@@ -992,7 +992,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_sr
with unsigned time_t tmp+= shift*86400L might result in a number,
larger then TIMESTAMP_MAX_VALUE, so another check will work.
*/
- if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE))
+ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(tmp))
tmp= 0;
return (my_time_t) tmp;
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2010-12-29 00:26:31 +0000
+++ b/sql/field.cc 2011-02-02 13:53:56 +0000
@@ -9073,6 +9073,7 @@ void Create_field::create_length_to_inte
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VARCHAR:
=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc 2011-01-11 09:07:37 +0000
+++ b/sql/filesort.cc 2011-02-02 11:54:49 +0000
@@ -324,8 +324,24 @@ ha_rows filesort(THD *thd, TABLE *table,
}
}
if (error)
- my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
- MYF(ME_ERROR+ME_WAITTANG));
+ {
+ DBUG_ASSERT(thd->is_error());
+ my_printf_error(ER_FILSORT_ABORT,
+ "%s: %s",
+ MYF(ME_ERROR + ME_WAITTANG),
+ ER_THD(thd, ER_FILSORT_ABORT),
+ thd->stmt_da->message());
+
+ if (global_system_variables.log_warnings > 1)
+ {
+ sql_print_warning("%s, host: %s, user: %s, thread: %lu, query: %-.4096s",
+ ER_THD(thd, ER_FILSORT_ABORT),
+ thd->security_ctx->host_or_ip,
+ &thd->security_ctx->priv_user[0],
+ (ulong) thd->thread_id,
+ thd->query());
+ }
+ }
else
statistic_add(thd->status_var.filesort_rows,
(ulong) records, &LOCK_status);
@@ -369,6 +385,9 @@ static char **make_char_array(char **old
char *char_pos;
DBUG_ENTER("make_char_array");
+ DBUG_EXECUTE_IF("make_char_array_fail",
+ DBUG_SET("+d,simulate_out_of_memory"););
+
if (old_pos ||
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
my_flag)))
=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc 2010-12-29 00:26:31 +0000
+++ b/sql/item_sum.cc 2011-02-02 09:18:44 +0000
@@ -556,24 +556,27 @@ Item *Item_sum::set_arg(uint i, THD *thd
int Item_sum::set_aggregator(Aggregator::Aggregator_type aggregator)
{
- if (aggr)
+ /*
+ Dependent subselects may be executed multiple times, making
+ set_aggregator to be called multiple times. The aggregator type
+ will be the same, but it needs to be reset so that it is
+ reevaluated with the new dependent data.
+ This function may also be called multiple times during query optimization.
+ In this case, the type may change, so we delete the old aggregator,
+ and create a new one.
+ */
+ if (aggr && aggregator == aggr->Aggrtype())
{
- /*
- Dependent subselects may be executed multiple times, making
- set_aggregator to be called multiple times. The aggregator type
- will be the same, but it needs to be reset so that it is
- reevaluated with the new dependent data.
- */
- DBUG_ASSERT(aggregator == aggr->Aggrtype());
aggr->clear();
return FALSE;
}
+
+ delete aggr;
switch (aggregator)
{
case Aggregator::DISTINCT_AGGREGATOR:
aggr= new Aggregator_distinct(this);
break;
-
case Aggregator::SIMPLE_AGGREGATOR:
aggr= new Aggregator_simple(this);
break;
=== modified file 'sql/item_sum.h'
--- a/sql/item_sum.h 2011-01-17 09:39:59 +0000
+++ b/sql/item_sum.h 2011-02-02 09:18:44 +0000
@@ -461,10 +461,9 @@ public:
*/
virtual void no_rows_in_result()
{
- if (!aggr)
- set_aggregator(with_distinct ?
- Aggregator::DISTINCT_AGGREGATOR :
- Aggregator::SIMPLE_AGGREGATOR);
+ set_aggregator(with_distinct ?
+ Aggregator::DISTINCT_AGGREGATOR :
+ Aggregator::SIMPLE_AGGREGATOR);
aggregator_clear();
}
virtual void make_unique() { force_copy_fields= TRUE; }
@@ -515,11 +514,10 @@ public:
quick_group= with_distinct ? 0 : 1;
}
- /**
+ /*
Set the type of aggregation : DISTINCT or not.
- Called when the final determination is done about the aggregation
- type and the object is about to be used.
+ May be called multiple times.
*/
int set_aggregator(Aggregator::Aggregator_type aggregator);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2011-01-17 07:44:37 +0000
+++ b/sql/mysqld.cc 2011-02-04 04:59:55 +0000
@@ -2879,6 +2879,19 @@ sizeof(load_default_groups)/sizeof(load_
#endif
+#ifndef EMBEDDED_LIBRARY
+static
+int
+check_enough_stack_size()
+{
+ uchar stack_top;
+
+ return check_stack_overrun(current_thd, STACK_MIN_SIZE,
+ &stack_top);
+}
+#endif
+
+
/**
Initialize one of the global date/time format variables.
@@ -3080,12 +3093,6 @@ static int init_common_variables()
max_system_variables.pseudo_thread_id= (ulong)~0;
server_start_time= flush_status_time= my_time(0);
- /* TODO: remove this when my_time_t is 64 bit compatible */
- if (server_start_time >= (time_t) MY_TIME_T_MAX)
- {
- sql_print_error("This MySQL server doesn't support dates later then 2038");
- return 1;
- }
rpl_filter= new Rpl_filter;
binlog_filter= new Rpl_filter;
@@ -3124,6 +3131,13 @@ static int init_common_variables()
*/
mysql_bin_log.init_pthread_objects();
+ /* TODO: remove this when my_time_t is 64 bit compatible */
+ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
+ {
+ sql_print_error("This MySQL server doesn't support dates later then 2038");
+ return 1;
+ }
+
if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
{
strmake(glob_hostname, STRING_WITH_LEN("localhost"));
@@ -3339,7 +3353,11 @@ static int init_common_variables()
if (item_create_init())
return 1;
item_init();
- my_regex_init(&my_charset_latin1);
+#ifndef EMBEDDED_LIBRARY
+ my_regex_init(&my_charset_latin1, check_enough_stack_size);
+#else
+ my_regex_init(&my_charset_latin1, NULL);
+#endif
/*
Process a comma-separated character set list and choose
the first available character set. This is mostly for
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2010-11-12 12:56:21 +0000
+++ b/sql/protocol.cc 2011-02-02 11:54:49 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved.
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
@@ -543,9 +543,10 @@ bool Protocol::send_ok(uint server_statu
const char *message)
{
DBUG_ENTER("Protocol::send_ok");
-
- DBUG_RETURN(net_send_ok(thd, server_status, statement_warn_count,
- affected_rows, last_insert_id, message));
+ const bool retval=
+ net_send_ok(thd, server_status, statement_warn_count,
+ affected_rows, last_insert_id, message);
+ DBUG_RETURN(retval);
}
@@ -558,8 +559,8 @@ bool Protocol::send_ok(uint server_statu
bool Protocol::send_eof(uint server_status, uint statement_warn_count)
{
DBUG_ENTER("Protocol::send_eof");
-
- DBUG_RETURN(net_send_eof(thd, server_status, statement_warn_count));
+ const bool retval= net_send_eof(thd, server_status, statement_warn_count);
+ DBUG_RETURN(retval);
}
@@ -573,8 +574,8 @@ bool Protocol::send_error(uint sql_errno
const char *sql_state)
{
DBUG_ENTER("Protocol::send_error");
-
- DBUG_RETURN(net_send_error_packet(thd, sql_errno, err_msg, sql_state));
+ const bool retval= net_send_error_packet(thd, sql_errno, err_msg, sql_state);
+ DBUG_RETURN(retval);
}
=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt 2010-11-05 17:42:37 +0000
+++ b/sql/share/errmsg-utf8.txt 2011-02-02 11:54:49 +0000
@@ -897,7 +897,7 @@ ER_OUT_OF_SORTMEMORY HY001 S1001
cze "M-B��lo pam��ti pro t����dlse. ��g sorteringshukommelse (sort buffer size) for serveren"
nla "Geen geheugen om te sorteren. Verhoog de server sort buffer size"
- eng "Out of sort memory; increase server sort buffer size"
+ eng "Out of sort memory, consider increasing server sort buffer size"
jps "Out of sort memory. sort buffer size ���������������������������.",
est "M��lu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit"
fre "Manque de m��moire pour le tri. Augmentez-la."
@@ -907,10 +907,10 @@ ER_OUT_OF_SORTMEMORY HY001 S1001
ita "Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone"
jpn "Out of sort memory. sort buffer size ������fer��� ��������� �����e mer sorteringsminne. ��k sorteringsminnet (sort buffer size) for tjenesten"
- norwegian-ny "Ikkje meir sorteringsminne. Auk sorteringsminnet (sorteringsbffer storleik) for tenesten"
+ nor "Ikke mer sorteringsminne. Vurder �� ��ke sorteringsminnet (sort buffer size) for tjenesten"
+ norwegian-ny "Ikkje meir sorteringsminne. Vurder �� auke sorteringsminnet (sorteringsbuffer storleik) for tenesten"
pol "Zbyt ma��o pami��ci dla sortowania. Zwi��ksz wielko?�� bufora demona dla sortowania"
- por "Sem mem��ria para ordena����o. Aumente tamanho do 'buffer' de ordena����o"
+ por "N��o h�� mem��ria suficiente para ordena����o. Considere aumentar o tamanho do retentor (buffer) de ordena����o."
rum "Out of memory pentru sortare. Largeste marimea buffer-ului pentru sortare in daemon (sort buffer size)"
rus "����������������� ������ � ������������������ ����� �������������������"
serbian "Nema memorije za sortiranje. Pove��ajte veli��inu sort buffer-a MySQL server-u"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-12-29 00:26:31 +0000
+++ b/sql/sql_class.h 2011-02-02 18:13:28 +0000
@@ -2280,7 +2280,7 @@ public:
/*TODO: this will be obsolete when we have support for 64 bit my_time_t */
inline bool is_valid_time()
{
- return (start_time < (time_t) MY_TIME_T_MAX);
+ return (IS_TIME_T_VALID_FOR_TIMESTAMP(start_time));
}
void set_time_after_lock() { utime_after_lock= my_micro_time(); }
ulonglong current_utime() { return my_micro_time(); }
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-11-29 03:04:16 +0000
+++ b/sql/sql_insert.cc 2011-01-31 13:11:05 +0000
@@ -979,7 +979,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
- if ((changed && error <= 0) ||
+ if (error <= 0 ||
thd->transaction.stmt.modified_non_trans_table ||
was_insert_delayed)
{
=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc 2011-01-24 03:52:29 +0000
+++ b/sql/sql_repl.cc 2011-01-31 13:11:05 +0000
@@ -676,8 +676,11 @@ impossible position";
file */
if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg))
goto err;
+
+ my_off_t prev_pos= pos;
while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
{
+ prev_pos= my_b_tell(&log);
#ifndef DBUG_OFF
if (max_binlog_dump_events && !left_events--)
{
@@ -767,8 +770,13 @@ impossible position";
here we were reading binlog that was not closed properly (as a result
of a crash ?). treat any corruption as EOF
*/
- if (binlog_can_be_corrupted && error != LOG_READ_MEM)
+ if (binlog_can_be_corrupted &&
+ error != LOG_READ_MEM && error != LOG_READ_EOF)
+ {
+ my_b_seek(&log, prev_pos);
error=LOG_READ_EOF;
+ }
+
/*
TODO: now that we are logging the offset, check to make sure
the recorded offset and the actual match.
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2011-01-13 10:42:48 +0000
+++ b/sql/sql_select.cc 2011-02-01 14:19:34 +0000
@@ -3365,26 +3365,7 @@ add_key_field(KEY_FIELD **key_fields,uin
eq_func is NEVER true when num_values > 1
*/
if (!eq_func)
- {
- /*
- Additional optimization: if we're processing
- "t.key BETWEEN c1 AND c1" then proceed as if we were processing
- "t.key = c1".
- TODO: This is a very limited fix. A more generic fix is possible.
- There are 2 options:
- A) Make equality propagation code be able to handle BETWEEN
- (including cases like t1.key BETWEEN t2.key AND t3.key)
- B) Make range optimizer to infer additional "t.key = c" equalities
- and use them in equality propagation process (see details in
- OptimizerKBAndTodo)
- */
- if ((cond->functype() != Item_func::BETWEEN) ||
- ((Item_func_between*) cond)->negated ||
- !value[0]->eq(value[1], field->binary()))
- return;
- eq_func= TRUE;
- }
-
+ return;
if (field->result_type() == STRING_RESULT)
{
if ((*value)->result_type() != STRING_RESULT)
@@ -3580,9 +3561,65 @@ add_key_fields(JOIN *join, KEY_FIELD **k
case Item_func::OPTIMIZE_KEY:
{
Item **values;
- // BETWEEN, IN, NE
- if (is_local_field (cond_func->key_item()) &&
- !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
+ /*
+ Build list of possible keys for 'a BETWEEN low AND high'.
+ It is handled similar to the equivalent condition
+ 'a >= low AND a <= high':
+ */
+ if (cond_func->functype() == Item_func::BETWEEN)
+ {
+ Item_field *field_item;
+ bool equal_func= FALSE;
+ uint num_values= 2;
+ values= cond_func->arguments();
+
+ bool binary_cmp= (values[0]->real_item()->type() == Item::FIELD_ITEM)
+ ? ((Item_field*)values[0]->real_item())->field->binary()
+ : TRUE;
+
+ /*
+ Additional optimization: If 'low = high':
+ Handle as if the condition was "t.key = low".
+ */
+ if (!((Item_func_between*)cond_func)->negated &&
+ values[1]->eq(values[2], binary_cmp))
+ {
+ equal_func= TRUE;
+ num_values= 1;
+ }
+
+ /*
+ Append keys for 'field <cmp> value[]' if the
+ condition is of the form::
+ '<field> BETWEEN value[1] AND value[2]'
+ */
+ if (is_local_field (values[0]))
+ {
+ field_item= (Item_field *) (values[0]->real_item());
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ field_item, equal_func, &values[1],
+ num_values, usable_tables, sargables);
+ }
+ /*
+ Append keys for 'value[0] <cmp> field' if the
+ condition is of the form:
+ 'value[0] BETWEEN field1 AND field2'
+ */
+ for (uint i= 1; i <= num_values; i++)
+ {
+ if (is_local_field (values[i]))
+ {
+ field_item= (Item_field *) (values[i]->real_item());
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ field_item, equal_func, values,
+ 1, usable_tables, sargables);
+ }
+ }
+ } // if ( ... Item_func::BETWEEN)
+
+ // IN, NE
+ else if (is_local_field (cond_func->key_item()) &&
+ !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
values= cond_func->arguments()+1;
if (cond_func->functype() == Item_func::NE_FUNC &&
@@ -3596,21 +3633,6 @@ add_key_fields(JOIN *join, KEY_FIELD **k
cond_func->argument_count()-1,
usable_tables, sargables);
}
- if (cond_func->functype() == Item_func::BETWEEN)
- {
- values= cond_func->arguments();
- for (uint i= 1 ; i < cond_func->argument_count() ; i++)
- {
- Item_field *field_item;
- if (is_local_field (cond_func->arguments()[i]))
- {
- field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
- add_key_equal_fields(key_fields, *and_level, cond_func,
- field_item, 0, values, 1, usable_tables,
- sargables);
- }
- }
- }
break;
}
case Item_func::OPTIMIZE_OP:
@@ -11745,17 +11767,40 @@ evaluate_join_record(JOIN *join, JOIN_TA
first_unmatched->found= 1;
for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
{
- if (tab->table->reginfo.not_exists_optimize)
- return NESTED_LOOP_NO_MORE_ROWS;
/* Check all predicates that has just been activated. */
/*
Actually all predicates non-guarded by first_unmatched->found
will be re-evaluated again. It could be fixed, but, probably,
it's not worth doing now.
*/
+ /*
+ not_exists_optimize has been created from a
+ select_cond containing 'is_null'. This 'is_null'
+ predicate is still present on any 'tab' with
+ 'not_exists_optimize'. Furthermore, the usual rules
+ for condition guards also applies for
+ 'not_exists_optimize' -> When 'is_null==false' we
+ know all cond. guards are open and we can apply
+ the 'not_exists_optimize'.
+ */
+ DBUG_ASSERT(!(tab->table->reginfo.not_exists_optimize &&
+ !tab->select_cond));
+
if (tab->select_cond && !tab->select_cond->val_int())
{
/* The condition attached to table tab is false */
+
+ if (tab->table->reginfo.not_exists_optimize)
+ {
+ /*
+ When not_exists_optimize is set: No need to further
+ explore more rows of 'tab' for this partial result.
+ Any found 'tab' matches are known to evaluate to 'false'.
+ Returning .._NO_MORE_ROWS will skip rem. 'tab' rows.
+ */
+ return NESTED_LOOP_NO_MORE_ROWS;
+ }
+
if (tab == join_tab)
found= 0;
else
=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc 2010-12-17 11:11:34 +0000
+++ b/sql/sys_vars.cc 2011-02-02 18:13:28 +0000
@@ -2430,17 +2430,17 @@ static ulonglong read_timestamp(THD *thd
static bool check_timestamp(sys_var *self, THD *thd, set_var *var)
{
- time_t val;
+ longlong val;
if (!var->value)
return FALSE;
- val= (time_t) var->save_result.ulonglong_value;
- if (val < (time_t) MY_TIME_T_MIN || val > (time_t) MY_TIME_T_MAX)
+ val= (longlong) var->save_result.ulonglong_value;
+ if (val != 0 && // this is how you set the default value
+ (val < TIMESTAMP_MIN_VALUE || val > TIMESTAMP_MAX_VALUE))
{
- my_message(ER_UNKNOWN_ERROR,
- "This version of MySQL doesn't support dates later than 2038",
- MYF(0));
+ char buf[64];
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "timestamp", llstr(val, buf));
return TRUE;
}
return FALSE;
=== modified file 'sql/unireg.h'
--- a/sql/unireg.h 2010-07-02 19:38:04 +0000
+++ b/sql/unireg.h 2011-02-02 11:54:49 +0000
@@ -1,7 +1,7 @@
#ifndef UNIREG_INCLUDED
#define UNIREG_INCLUDED
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -56,8 +56,6 @@ typedef struct st_ha_create_information
#define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, X) : ER_DEFAULT(X))
-#define ERRMAPP 1 /* Errormap f|r my_error */
-
#define ME_INFO (ME_HOLDTANG+ME_OLDWIN+ME_NOREFRESH)
#define ME_ERROR (ME_BELL+ME_OLDWIN+ME_NOREFRESH)
#define MYF_RW MYF(MY_WME+MY_NABP) /* Vid my_read & my_write */
=== modified file 'storage/innobase/btr/btr0btr.c'
--- a/storage/innobase/btr/btr0btr.c 2011-01-06 07:19:02 +0000
+++ b/storage/innobase/btr/btr0btr.c 2011-01-25 08:51:13 +0000
@@ -981,7 +981,7 @@ btr_page_reorganize_low(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
#ifndef UNIV_HOTBACKUP
- temp_block = buf_block_alloc(buf_pool, 0);
+ temp_block = buf_block_alloc(buf_pool);
#else /* !UNIV_HOTBACKUP */
ut_ad(block == back_block1);
temp_block = back_block2;
=== modified file 'storage/innobase/btr/btr0cur.c'
--- a/storage/innobase/btr/btr0cur.c 2010-12-21 12:05:10 +0000
+++ b/storage/innobase/btr/btr0cur.c 2011-01-28 09:10:40 +0000
@@ -111,6 +111,18 @@ can be released by page reorganize, then
/*--------------------------------------*/
#define BTR_BLOB_HDR_SIZE 8 /*!< Size of a BLOB
part header, in bytes */
+
+/** Estimated table level stats from sampled value.
+@param value sampled stats
+@param index index being sampled
+@param sample number of sampled rows
+@param ext_size external stored data size
+@param not_empty table not empty
+@return estimated table wide stats from sampled value */
+#define BTR_TABLE_STATS_FROM_SAMPLE(value, index, sample, ext_size, not_empty)\
+ (((value) * (ib_int64_t) index->stat_n_leaf_pages \
+ + (sample) - 1 + (ext_size) + (not_empty)) / ((sample) + (ext_size)))
+
/* @} */
#endif /* !UNIV_HOTBACKUP */
@@ -3479,9 +3491,54 @@ btr_estimate_n_rows_in_range(
}
/*******************************************************************//**
+Record the number of non_null key values in a given index for
+each n-column prefix of the index where n < dict_index_get_n_unique(index).
+The estimates are eventually stored in the array:
+index->stat_n_non_null_key_vals. */
+static
+void
+btr_record_not_null_field_in_rec(
+/*=============================*/
+ rec_t* rec, /*!< in: physical record */
+ ulint n_unique, /*!< in: dict_index_get_n_unique(index),
+ number of columns uniquely determine
+ an index entry */
+ const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
+ its size could be for all fields or
+ that of "n_unique" */
+ ib_int64_t* n_not_null) /*!< in/out: array to record number of
+ not null rows for n-column prefix */
+{
+ ulint i;
+
+ ut_ad(rec_offs_n_fields(offsets) >= n_unique);
+
+ if (n_not_null == NULL) {
+ return;
+ }
+
+ for (i = 0; i < n_unique; i++) {
+ ulint rec_len;
+ byte* field;
+
+ field = rec_get_nth_field(rec, offsets, i, &rec_len);
+
+ if (rec_len != UNIV_SQL_NULL) {
+ n_not_null[i]++;
+ } else {
+ /* Break if we hit the first NULL value */
+ break;
+ }
+ }
+}
+
+/*******************************************************************//**
Estimates the number of different key values in a given index, for
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
-The estimates are stored in the array index->stat_n_diff_key_vals. */
+The estimates are stored in the array index->stat_n_diff_key_vals.
+If innodb_stats_method is "nulls_ignored", we also record the number of
+non-null values for each prefix and store the estimates in
+array index->stat_n_non_null_key_vals. */
UNIV_INTERN
void
btr_estimate_number_of_different_key_vals(
@@ -3495,6 +3552,8 @@ btr_estimate_number_of_different_key_val
ulint matched_fields;
ulint matched_bytes;
ib_int64_t* n_diff;
+ ib_int64_t* n_not_null;
+ ibool stats_null_not_equal;
ullint n_sample_pages; /* number of pages to sample */
ulint not_empty_flag = 0;
ulint total_external_size = 0;
@@ -3503,16 +3562,43 @@ btr_estimate_number_of_different_key_val
ullint add_on;
mtr_t mtr;
mem_heap_t* heap = NULL;
- ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
- ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets_rec = offsets_rec_;
- ulint* offsets_next_rec= offsets_next_rec_;
- rec_offs_init(offsets_rec_);
- rec_offs_init(offsets_next_rec_);
+ ulint* offsets_rec = NULL;
+ ulint* offsets_next_rec = NULL;
n_cols = dict_index_get_n_unique(index);
- n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
+ heap = mem_heap_create((sizeof *n_diff + sizeof *n_not_null)
+ * (n_cols + 1)
+ + dict_index_get_n_fields(index)
+ * (sizeof *offsets_rec
+ + sizeof *offsets_next_rec));
+
+ n_diff = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
+
+ n_not_null = NULL;
+
+ /* Check srv_innodb_stats_method setting, and decide whether we
+ need to record non-null value and also decide if NULL is
+ considered equal (by setting stats_null_not_equal value) */
+ switch (srv_innodb_stats_method) {
+ case SRV_STATS_NULLS_IGNORED:
+ n_not_null = mem_heap_zalloc(heap, (n_cols + 1)
+ * sizeof *n_not_null);
+ /* fall through */
+
+ case SRV_STATS_NULLS_UNEQUAL:
+ /* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL
+ case, we will treat NULLs as unequal value */
+ stats_null_not_equal = TRUE;
+ break;
+
+ case SRV_STATS_NULLS_EQUAL:
+ stats_null_not_equal = FALSE;
+ break;
+
+ default:
+ ut_error;
+ }
/* It makes no sense to test more pages than are contained
in the index, thus we lower the number if it is too high */
@@ -3529,7 +3615,6 @@ btr_estimate_number_of_different_key_val
/* We sample some pages in the index to get an estimate */
for (i = 0; i < n_sample_pages; i++) {
- rec_t* supremum;
mtr_start(&mtr);
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@@ -3542,18 +3627,25 @@ btr_estimate_number_of_different_key_val
page = btr_cur_get_page(&cursor);
- supremum = page_get_supremum_rec(page);
rec = page_rec_get_next(page_get_infimum_rec(page));
- if (rec != supremum) {
+ if (!page_rec_is_supremum(rec)) {
not_empty_flag = 1;
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
ULINT_UNDEFINED, &heap);
+
+ if (n_not_null) {
+ btr_record_not_null_field_in_rec(
+ rec, n_cols, offsets_rec, n_not_null);
+ }
}
- while (rec != supremum) {
+ while (!page_rec_is_supremum(rec)) {
rec_t* next_rec = page_rec_get_next(rec);
- if (next_rec == supremum) {
+ if (page_rec_is_supremum(next_rec)) {
+ total_external_size +=
+ btr_rec_get_externally_stored_len(
+ rec, offsets_rec);
break;
}
@@ -3561,11 +3653,13 @@ btr_estimate_number_of_different_key_val
matched_bytes = 0;
offsets_next_rec = rec_get_offsets(next_rec, index,
offsets_next_rec,
- n_cols, &heap);
+ ULINT_UNDEFINED,
+ &heap);
cmp_rec_rec_with_match(rec, next_rec,
offsets_rec, offsets_next_rec,
- index, &matched_fields,
+ index, stats_null_not_equal,
+ &matched_fields,
&matched_bytes);
for (j = matched_fields + 1; j <= n_cols; j++) {
@@ -3575,6 +3669,12 @@ btr_estimate_number_of_different_key_val
n_diff[j]++;
}
+ if (n_not_null) {
+ btr_record_not_null_field_in_rec(
+ next_rec, n_cols, offsets_next_rec,
+ n_not_null);
+ }
+
total_external_size
+= btr_rec_get_externally_stored_len(
rec, offsets_rec);
@@ -3609,10 +3709,6 @@ btr_estimate_number_of_different_key_val
}
}
- offsets_rec = rec_get_offsets(rec, index, offsets_rec,
- ULINT_UNDEFINED, &heap);
- total_external_size += btr_rec_get_externally_stored_len(
- rec, offsets_rec);
mtr_commit(&mtr);
}
@@ -3626,13 +3722,9 @@ btr_estimate_number_of_different_key_val
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j]
- = ((n_diff[j]
- * (ib_int64_t)index->stat_n_leaf_pages
- + n_sample_pages - 1
- + total_external_size
- + not_empty_flag)
- / (n_sample_pages
- + total_external_size));
+ = BTR_TABLE_STATS_FROM_SAMPLE(
+ n_diff[j], index, n_sample_pages,
+ total_external_size, not_empty_flag);
/* If the tree is small, smaller than
10 * n_sample_pages + total_external_size, then
@@ -3651,12 +3743,20 @@ btr_estimate_number_of_different_key_val
}
index->stat_n_diff_key_vals[j] += add_on;
- }
- mem_free(n_diff);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
+ /* Update the stat_n_non_null_key_vals[] with our
+ sampled result. stat_n_non_null_key_vals[] is created
+ and initialized to zero in dict_index_add_to_cache(),
+ along with stat_n_diff_key_vals[] array */
+ if (n_not_null != NULL && (j < n_cols)) {
+ index->stat_n_non_null_key_vals[j] =
+ BTR_TABLE_STATS_FROM_SAMPLE(
+ n_not_null[j], index, n_sample_pages,
+ total_external_size, not_empty_flag);
+ }
}
+
+ mem_heap_free(heap);
}
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
@@ -3946,13 +4046,12 @@ btr_blob_free(
&& buf_block_get_space(block) == space
&& buf_block_get_page_no(block) == page_no) {
- if (buf_LRU_free_block(&block->page, all, NULL)
- != BUF_LRU_FREED
+ if (buf_LRU_free_block(&block->page, all) != BUF_LRU_FREED
&& all && block->page.zip.data) {
/* Attempt to deallocate the uncompressed page
if the whole block cannot be deallocted. */
- buf_LRU_free_block(&block->page, FALSE, NULL);
+ buf_LRU_free_block(&block->page, FALSE);
}
}
=== modified file 'storage/innobase/btr/btr0sea.c'
--- a/storage/innobase/btr/btr0sea.c 2010-10-01 13:36:35 +0000
+++ b/storage/innobase/btr/btr0sea.c 2011-01-25 08:51:13 +0000
@@ -151,7 +151,7 @@ btr_search_check_free_space_in_heap(void
be enough free space in the hash table. */
if (heap->free_block == NULL) {
- buf_block_t* block = buf_block_alloc(NULL, 0);
+ buf_block_t* block = buf_block_alloc(NULL);
rw_lock_x_lock(&btr_search_latch);
=== modified file 'storage/innobase/buf/buf0buddy.c'
--- a/storage/innobase/buf/buf0buddy.c 2010-10-20 11:46:28 +0000
+++ b/storage/innobase/buf/buf0buddy.c 2011-01-25 08:51:13 +0000
@@ -327,7 +327,7 @@ buf_buddy_alloc_low(
/* Try replacing an uncompressed page in the buffer pool. */
buf_pool_mutex_exit(buf_pool);
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
*lru = TRUE;
buf_pool_mutex_enter(buf_pool);
=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c 2011-01-06 07:19:02 +0000
+++ b/storage/innobase/buf/buf0buf.c 2011-01-25 08:51:13 +0000
@@ -416,9 +416,9 @@ UNIV_INTERN
buf_block_t*
buf_block_alloc(
/*============*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ulint zip_size) /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance,
+ or NULL for round-robin selection
+ of the buffer pool */
{
buf_block_t* block;
ulint index;
@@ -431,7 +431,7 @@ buf_block_alloc(
buf_pool = buf_pool_from_array(index);
}
- block = buf_LRU_get_free_block(buf_pool, zip_size);
+ block = buf_LRU_get_free_block(buf_pool);
buf_block_set_state(block, BUF_BLOCK_MEMORY);
@@ -1623,7 +1623,7 @@ shrink_again:
buf_LRU_make_block_old(&block->page);
dirty++;
- } else if (buf_LRU_free_block(&block->page, TRUE, NULL)
+ } else if (buf_LRU_free_block(&block->page, TRUE)
!= BUF_LRU_FREED) {
nonfree++;
}
@@ -2366,8 +2366,7 @@ err_exit:
mutex_enter(block_mutex);
/* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE, NULL)
- == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) {
mutex_exit(block_mutex);
goto lookup;
@@ -2883,7 +2882,7 @@ wait_until_unfixed:
buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
ut_a(block);
buf_pool_mutex_enter(buf_pool);
@@ -3013,8 +3012,7 @@ wait_until_unfixed:
/* Try to evict the block from the buffer pool, to use the
insert buffer (change buffer) as much as possible. */
- if (buf_LRU_free_block(&block->page, TRUE, NULL)
- == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(&block->page, TRUE) == BUF_LRU_FREED) {
mutex_exit(&block->mutex);
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
@@ -3588,7 +3586,7 @@ buf_page_init_for_read(
&& UNIV_LIKELY(!recv_recovery_is_on())) {
block = NULL;
} else {
- block = buf_LRU_get_free_block(buf_pool, 0);
+ block = buf_LRU_get_free_block(buf_pool);
ut_ad(block);
ut_ad(buf_pool_from_block(block) == buf_pool);
}
@@ -3794,7 +3792,7 @@ buf_page_create(
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(space || !zip_size);
- free_block = buf_LRU_get_free_block(buf_pool, 0);
+ free_block = buf_LRU_get_free_block(buf_pool);
fold = buf_page_address_fold(space, offset);
=== modified file 'storage/innobase/buf/buf0lru.c'
--- a/storage/innobase/buf/buf0lru.c 2010-12-09 09:32:53 +0000
+++ b/storage/innobase/buf/buf0lru.c 2011-01-25 08:51:13 +0000
@@ -603,7 +603,7 @@ buf_LRU_free_from_unzip_LRU_list(
ut_ad(block->page.in_LRU_list);
mutex_enter(&block->mutex);
- freed = buf_LRU_free_block(&block->page, FALSE, NULL);
+ freed = buf_LRU_free_block(&block->page, FALSE);
mutex_exit(&block->mutex);
switch (freed) {
@@ -666,7 +666,7 @@ buf_LRU_free_from_common_LRU_list(
mutex_enter(block_mutex);
accessed = buf_page_is_accessed(bpage);
- freed = buf_LRU_free_block(bpage, TRUE, NULL);
+ freed = buf_LRU_free_block(bpage, TRUE);
mutex_exit(block_mutex);
switch (freed) {
@@ -858,9 +858,7 @@ UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(
/*===================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ulint zip_size) /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
{
buf_block_t* block = NULL;
ibool freed;
@@ -936,31 +934,11 @@ loop:
/* If there is a block in the free list, take it */
block = buf_LRU_get_free_only(buf_pool);
- if (block) {
+ buf_pool_mutex_exit(buf_pool);
+ if (block) {
ut_ad(buf_pool_from_block(block) == buf_pool);
-
-#ifdef UNIV_DEBUG
- block->page.zip.m_start =
-#endif /* UNIV_DEBUG */
- block->page.zip.m_end =
- block->page.zip.m_nonempty =
- block->page.zip.n_blobs = 0;
-
- if (UNIV_UNLIKELY(zip_size)) {
- ibool lru;
- page_zip_set_size(&block->page.zip, zip_size);
-
- block->page.zip.data = buf_buddy_alloc(
- buf_pool, zip_size, &lru);
-
- UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
- } else {
- page_zip_set_size(&block->page.zip, 0);
- block->page.zip.data = NULL;
- }
-
- buf_pool_mutex_exit(buf_pool);
+ memset(&block->page.zip, 0, sizeof block->page.zip);
if (started_monitor) {
srv_print_innodb_monitor = mon_value_was;
@@ -972,8 +950,6 @@ loop:
/* If no block was in the free list, search from the end of the LRU
list and try to free a block there */
- buf_pool_mutex_exit(buf_pool);
-
freed = buf_LRU_search_and_free_block(buf_pool, n_iterations);
if (freed > 0) {
@@ -1456,12 +1432,8 @@ enum buf_lru_free_block_status
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
- ibool zip, /*!< in: TRUE if should remove also the
+ ibool zip) /*!< in: TRUE if should remove also the
compressed page of an uncompressed page */
- ibool* buf_pool_mutex_released)
- /*!< in: pointer to a variable that will
- be assigned TRUE if buf_pool_mutex
- was temporarily released, or NULL */
{
buf_page_t* b = NULL;
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
@@ -1638,10 +1610,6 @@ alloc:
b->io_fix = BUF_IO_READ;
}
- if (buf_pool_mutex_released) {
- *buf_pool_mutex_released = TRUE;
- }
-
buf_pool_mutex_exit(buf_pool);
mutex_exit(block_mutex);
=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c 2011-01-05 13:47:15 +0000
+++ b/storage/innobase/dict/dict0dict.c 2011-01-15 07:24:47 +0000
@@ -1689,6 +1689,12 @@ undo_size_ok:
new_index->heap,
(1 + dict_index_get_n_unique(new_index))
* sizeof(ib_int64_t));
+
+ new_index->stat_n_non_null_key_vals = mem_heap_zalloc(
+ new_index->heap,
+ (1 + dict_index_get_n_unique(new_index))
+ * sizeof(*new_index->stat_n_non_null_key_vals));
+
/* Give some sensible values to stat_n_... in case we do
not calculate statistics quickly enough */
@@ -4319,6 +4325,10 @@ dict_update_statistics(
for (i = dict_index_get_n_unique(index); i; ) {
index->stat_n_diff_key_vals[i--] = 1;
}
+
+ memset(index->stat_n_non_null_key_vals, 0,
+ (1 + dict_index_get_n_unique(index))
+ * sizeof(*index->stat_n_non_null_key_vals));
}
index = dict_table_get_next_index(index);
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2011-01-26 13:23:29 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2011-01-30 16:51:37 +0000
@@ -172,6 +172,25 @@ static char* internal_innobase_data_file
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
+/** Possible values for system variable "innodb_stats_method". The values
+are defined the same as its corresponding MyISAM system variable
+"myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
+static const char* innodb_stats_method_names[] = {
+ "nulls_equal",
+ "nulls_unequal",
+ "nulls_ignored",
+ NullS
+};
+
+/** Used to define an enumerate type of the system variable innodb_stats_method.
+This is the same as "myisam_stats_method_typelib" */
+static TYPELIB innodb_stats_method_typelib = {
+ array_elements(innodb_stats_method_names) - 1,
+ "innodb_stats_method_typelib",
+ innodb_stats_method_names,
+ NULL
+};
+
/* The following counter is used to convey information to InnoDB
about server activity: in selects it is not sensible to call
srv_active_wake_master_thread after each fetch or search, we only do
@@ -7711,6 +7730,65 @@ innobase_get_mysql_key_number_for_index(
return(0);
}
+
+/*********************************************************************//**
+Calculate Record Per Key value. Need to exclude the NULL value if
+innodb_stats_method is set to "nulls_ignored"
+@return estimated record per key value */
+static
+ha_rows
+innodb_rec_per_key(
+/*===============*/
+ dict_index_t* index, /*!< in: dict_index_t structure */
+ ulint i, /*!< in: the column we are
+ calculating rec per key */
+ ha_rows records) /*!< in: estimated total records */
+{
+ ha_rows rec_per_key;
+
+ ut_ad(i < dict_index_get_n_unique(index));
+
+ /* Note the stat_n_diff_key_vals[] stores the diff value with
+ n-prefix indexing, so it is always stat_n_diff_key_vals[i + 1] */
+ if (index->stat_n_diff_key_vals[i + 1] == 0) {
+
+ rec_per_key = records;
+ } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
+ ib_int64_t num_null;
+
+ /* Number of rows with NULL value in this
+ field */
+ num_null = records - index->stat_n_non_null_key_vals[i];
+
+ /* In theory, index->stat_n_non_null_key_vals[i]
+ should always be less than the number of records.
+ Since this is statistics value, the value could
+ have slight discrepancy. But we will make sure
+ the number of null values is not a negative number. */
+ num_null = (num_null < 0) ? 0 : num_null;
+
+ /* If the number of NULL values is the same as or
+ large than that of the distinct values, we could
+ consider that the table consists mostly of NULL value.
+ Set rec_per_key to 1. */
+ if (index->stat_n_diff_key_vals[i + 1] <= num_null) {
+ rec_per_key = 1;
+ } else {
+ /* Need to exclude rows with NULL values from
+ rec_per_key calculation */
+ rec_per_key = (ha_rows)(
+ (records - num_null)
+ / (index->stat_n_diff_key_vals[i + 1]
+ - num_null));
+ }
+ } else {
+ rec_per_key = (ha_rows)
+ (records / index->stat_n_diff_key_vals[i + 1]);
+ }
+
+ return(rec_per_key);
+}
+
/*********************************************************************//**
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
@@ -7944,13 +8022,8 @@ ha_innobase::info_low(
break;
}
- if (index->stat_n_diff_key_vals[j + 1] == 0) {
-
- rec_per_key = stats.records;
- } else {
- rec_per_key = (ha_rows)(stats.records /
- index->stat_n_diff_key_vals[j + 1]);
- }
+ rec_per_key = innodb_rec_per_key(
+ index, j, stats.records);
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
@@ -11173,6 +11246,13 @@ static MYSQL_SYSVAR_STR(change_buffering
innodb_change_buffering_validate,
innodb_change_buffering_update, "all");
+static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
+ PLUGIN_VAR_RQCMDARG,
+ "Specifies how InnoDB index statistics collection code should "
+ "treat NULLs. Possible values are NULLS_EQUAL (default), "
+ "NULLS_UNEQUAL and NULLS_IGNORED",
+ NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
+
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
PLUGIN_VAR_RQCMDARG,
@@ -11229,6 +11309,7 @@ static struct st_mysql_sys_var* innobase
MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(stats_sample_pages),
MYSQL_SYSVAR(adaptive_hash_index),
+ MYSQL_SYSVAR(stats_method),
MYSQL_SYSVAR(replication_delay),
MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(strict_mode),
=== modified file 'storage/innobase/ibuf/ibuf0ibuf.c'
--- a/storage/innobase/ibuf/ibuf0ibuf.c 2010-12-01 13:09:02 +0000
+++ b/storage/innobase/ibuf/ibuf0ibuf.c 2011-01-27 08:12:00 +0000
@@ -2585,23 +2585,6 @@ ibuf_contract_ext(
if (UNIV_UNLIKELY(ibuf->empty)
&& UNIV_LIKELY(!srv_shutdown_state)) {
-ibuf_is_empty:
-
-#if 0 /* TODO */
- if (srv_shutdown_state) {
- /* If the insert buffer becomes empty during
- shutdown, note it in the system tablespace. */
-
- trx_sys_set_ibuf_format(TRX_SYS_IBUF_EMPTY);
- }
-
- /* TO DO: call trx_sys_set_ibuf_format() at startup
- and whenever ibuf_use is changed to allow buffered
- delete-marking or deleting. Never downgrade the
- stamped format except when the insert buffer becomes
- empty. */
-#endif
-
return(0);
}
@@ -2631,7 +2614,7 @@ ibuf_is_empty:
mtr_commit(&mtr);
btr_pcur_close(&pcur);
- goto ibuf_is_empty;
+ return(0);
}
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
=== modified file 'storage/innobase/include/btr0cur.h'
--- a/storage/innobase/include/btr0cur.h 2010-12-21 12:05:10 +0000
+++ b/storage/innobase/include/btr0cur.h 2011-01-15 07:24:47 +0000
@@ -466,7 +466,10 @@ btr_estimate_n_rows_in_range(
/*******************************************************************//**
Estimates the number of different key values in a given index, for
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
-The estimates are stored in the array index->stat_n_diff_key_vals. */
+The estimates are stored in the array index->stat_n_diff_key_vals.
+If innodb_stats_method is nulls_ignored, we also record the number of
+non-null values for each prefix and stored the estimates in
+array index->stat_n_non_null_key_vals. */
UNIV_INTERN
void
btr_estimate_number_of_different_key_vals(
=== modified file 'storage/innobase/include/buf0buf.h'
--- a/storage/innobase/include/buf0buf.h 2010-11-29 01:43:55 +0000
+++ b/storage/innobase/include/buf0buf.h 2011-01-25 08:51:13 +0000
@@ -276,9 +276,9 @@ UNIV_INTERN
buf_block_t*
buf_block_alloc(
/*============*/
- buf_pool_t* buf_pool, /*!< buffer pool instance */
- ulint zip_size); /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool); /*!< in: buffer pool instance,
+ or NULL for round-robin selection
+ of the buffer pool */
/********************************************************************//**
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
=== modified file 'storage/innobase/include/buf0lru.h'
--- a/storage/innobase/include/buf0lru.h 2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/buf0lru.h 2011-01-25 08:51:13 +0000
@@ -111,12 +111,9 @@ enum buf_lru_free_block_status
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
- ibool zip, /*!< in: TRUE if should remove also the
+ ibool zip) /*!< in: TRUE if should remove also the
compressed page of an uncompressed page */
- ibool* buf_pool_mutex_released);
- /*!< in: pointer to a variable that will
- be assigned TRUE if buf_pool->mutex
- was temporarily released, or NULL */
+ __attribute__((nonnull));
/******************************************************************//**
Try to free a replaceable block.
@return TRUE if found and freed */
@@ -153,9 +150,8 @@ UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(
/*===================*/
- buf_pool_t* buf_pool, /*!< in: preferred buffer pool */
- ulint zip_size); /*!< in: compressed page size in bytes,
- or 0 if uncompressed tablespace */
+ buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
+ __attribute__((nonnull,warn_unused_result));
/******************************************************************//**
Puts a block back to the free list. */
=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h 2010-11-30 18:25:52 +0000
+++ b/storage/innobase/include/dict0mem.h 2011-01-15 07:24:47 +0000
@@ -376,6 +376,12 @@ struct dict_index_struct{
dict_get_n_unique(index); we
periodically calculate new
estimates */
+ ib_int64_t* stat_n_non_null_key_vals;
+ /* approximate number of non-null key values
+ for this index, for each column where
+ n < dict_get_n_unique(index); This
+ is used when innodb_stats_method is
+ "nulls_ignored". */
ulint stat_index_size;
/*!< approximate index size in
database pages */
=== modified file 'storage/innobase/include/dict0types.h'
--- a/storage/innobase/include/dict0types.h 2010-07-21 14:22:29 +0000
+++ b/storage/innobase/include/dict0types.h 2011-01-17 12:11:43 +0000
@@ -33,11 +33,6 @@ typedef struct dict_index_struct dict_in
typedef struct dict_table_struct dict_table_t;
typedef struct dict_foreign_struct dict_foreign_t;
-/* A cluster object is a table object with the type field set to
-DICT_CLUSTERED */
-
-typedef dict_table_t dict_cluster_t;
-
typedef struct ind_node_struct ind_node_t;
typedef struct tab_node_struct tab_node_t;
=== modified file 'storage/innobase/include/rem0cmp.h'
--- a/storage/innobase/include/rem0cmp.h 2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/rem0cmp.h 2011-01-15 07:24:47 +0000
@@ -165,6 +165,10 @@ cmp_rec_rec_with_match(
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
dict_index_t* index, /*!< in: data dictionary index */
+ ibool nulls_unequal,
+ /* in: TRUE if this is for index statistics
+ cardinality estimation, and innodb_stats_method
+ is "nulls_unequal" or "nulls_ignored" */
ulint* matched_fields, /*!< in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
=== modified file 'storage/innobase/include/rem0cmp.ic'
--- a/storage/innobase/include/rem0cmp.ic 2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/rem0cmp.ic 2011-01-15 07:24:47 +0000
@@ -87,5 +87,5 @@ cmp_rec_rec(
ulint match_b = 0;
return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
- &match_f, &match_b));
+ FALSE, &match_f, &match_b));
}
=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h 2011-01-06 10:41:30 +0000
+++ b/storage/innobase/include/srv0srv.h 2011-01-15 07:24:47 +0000
@@ -172,6 +172,11 @@ capacity. PCT_IO(5) -> returns the numbe
is 5% of the max where max is srv_io_capacity. */
#define PCT_IO(p) ((ulong) (srv_io_capacity * ((double) p / 100.0)))
+/* The "innodb_stats_method" setting, decides how InnoDB is going
+to treat NULL value when collecting statistics. It is not defined
+as enum type because the configure option takes unsigned integer type. */
+extern ulong srv_innodb_stats_method;
+
#ifdef UNIV_LOG_ARCHIVE
extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
@@ -418,6 +423,19 @@ enum {
in connection with recovery */
};
+/* Alternatives for srv_innodb_stats_method, which could be changed by
+setting innodb_stats_method */
+enum srv_stats_method_name_enum {
+ SRV_STATS_NULLS_EQUAL, /* All NULL values are treated as
+ equal. This is the default setting
+ for innodb_stats_method */
+ SRV_STATS_NULLS_UNEQUAL, /* All NULL values are treated as
+ NOT equal. */
+ SRV_STATS_NULLS_IGNORED /* NULL values are ignored */
+};
+
+typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
+
#ifndef UNIV_HOTBACKUP
/** Types of threads existing in the system. */
enum srv_thread_type {
=== modified file 'storage/innobase/include/sync0rw.h'
--- a/storage/innobase/include/sync0rw.h 2011-01-04 09:46:20 +0000
+++ b/storage/innobase/include/sync0rw.h 2011-01-18 10:30:33 +0000
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -555,6 +555,7 @@ UNIV_INTERN
void
rw_lock_debug_print(
/*================*/
+ FILE* f, /*!< in: output stream */
rw_lock_debug_t* info); /*!< in: debug struct */
#endif /* UNIV_SYNC_DEBUG */
=== modified file 'storage/innobase/include/trx0rseg.h'
--- a/storage/innobase/include/trx0rseg.h 2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/trx0rseg.h 2011-01-17 12:11:43 +0000
@@ -141,9 +141,7 @@ struct trx_rseg_struct{
ulint id; /*!< rollback segment id == the index of
its slot in the trx system file copy */
mutex_t mutex; /*!< mutex protecting the fields in this
- struct except id; NOTE that the latching
- order must always be kernel mutex ->
- rseg mutex */
+ struct except id, which is constant */
ulint space; /*!< space where the rollback segment is
header is placed */
ulint zip_size;/* compressed page size of space
=== modified file 'storage/innobase/include/trx0trx.h'
--- a/storage/innobase/include/trx0trx.h 2010-10-21 11:22:27 +0000
+++ b/storage/innobase/include/trx0trx.h 2011-01-27 11:30:59 +0000
@@ -214,12 +214,12 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t *
trx_get_trx_by_xid(
/*===============*/
- XID* xid); /*!< in: X/Open XA transaction identification */
+ const XID* xid); /*!< in: X/Open XA transaction identifier */
/**********************************************************************//**
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE.
=== modified file 'storage/innobase/include/univ.i'
--- a/storage/innobase/include/univ.i 2011-01-08 14:52:36 +0000
+++ b/storage/innobase/include/univ.i 2011-01-10 13:37:55 +0000
@@ -429,7 +429,7 @@ it is read or written. */
/* Use sun_prefetch when compile with Sun Studio */
# define UNIV_EXPECT(expr,value) (expr)
# define UNIV_LIKELY_NULL(expr) (expr)
-# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many(addr)
+# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many((void*) addr)
# define UNIV_PREFETCH_RW(addr) sun_prefetch_write_many(addr)
#else
/* Dummy versions of the macros */
=== modified file 'storage/innobase/mem/mem0mem.c'
--- a/storage/innobase/mem/mem0mem.c 2010-07-29 09:09:00 +0000
+++ b/storage/innobase/mem/mem0mem.c 2011-01-25 08:51:13 +0000
@@ -347,7 +347,7 @@ mem_heap_create_block(
return(NULL);
}
} else {
- buf_block = buf_block_alloc(NULL, 0);
+ buf_block = buf_block_alloc(NULL);
}
block = (mem_block_t*) buf_block->frame;
=== modified file 'storage/innobase/mtr/mtr0log.c'
--- a/storage/innobase/mtr/mtr0log.c 2010-07-21 14:22:29 +0000
+++ b/storage/innobase/mtr/mtr0log.c 2011-01-25 10:35:35 +0000
@@ -408,7 +408,7 @@ mlog_parse_string(
ptr += 2;
if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
- || UNIV_UNLIKELY(len + offset) > UNIV_PAGE_SIZE) {
+ || UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
=== modified file 'storage/innobase/page/page0zip.c'
--- a/storage/innobase/page/page0zip.c 2010-07-21 14:22:29 +0000
+++ b/storage/innobase/page/page0zip.c 2011-01-25 08:51:13 +0000
@@ -4440,7 +4440,7 @@ page_zip_reorganize(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
#ifndef UNIV_HOTBACKUP
- temp_block = buf_block_alloc(buf_pool, 0);
+ temp_block = buf_block_alloc(buf_pool);
btr_search_drop_page_hash_index(block);
block->check_index_page_at_flush = TRUE;
#else /* !UNIV_HOTBACKUP */
=== modified file 'storage/innobase/rem/rem0cmp.c'
--- a/storage/innobase/rem/rem0cmp.c 2010-06-22 15:58:28 +0000
+++ b/storage/innobase/rem/rem0cmp.c 2011-01-15 07:24:47 +0000
@@ -862,6 +862,10 @@ cmp_rec_rec_with_match(
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
dict_index_t* index, /*!< in: data dictionary index */
+ ibool nulls_unequal,
+ /* in: TRUE if this is for index statistics
+ cardinality estimation, and innodb_stats_method
+ is "nulls_unequal" or "nulls_ignored" */
ulint* matched_fields, /*!< in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@@ -961,9 +965,13 @@ cmp_rec_rec_with_match(
|| rec2_f_len == UNIV_SQL_NULL) {
if (rec1_f_len == rec2_f_len) {
-
- goto next_field;
-
+ /* This is limited to stats collection,
+ cannot use it for regular search */
+ if (nulls_unequal) {
+ ret = -1;
+ } else {
+ goto next_field;
+ }
} else if (rec2_f_len == UNIV_SQL_NULL) {
/* We define the SQL null to be the
=== modified file 'storage/innobase/row/row0merge.c'
--- a/storage/innobase/row/row0merge.c 2010-11-11 05:51:00 +0000
+++ b/storage/innobase/row/row0merge.c 2011-01-28 09:38:21 +0000
@@ -2158,13 +2158,15 @@ row_merge_drop_temp_indexes(void)
}
/*********************************************************************//**
-Create a merge file. */
-static
-void
-row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
+Creates temperary merge files, and if UNIV_PFS_IO defined, register
+the file descriptor with Performance Schema.
+@return File descriptor */
+UNIV_INLINE
+int
+row_merge_file_create_low(void)
+/*===========================*/
{
+ int fd;
#ifdef UNIV_PFS_IO
/* This temp file open does not go through normal
file APIs, add instrumentation to register with
@@ -2176,37 +2178,59 @@ row_merge_file_create(
"Innodb Merge Temp File",
__FILE__, __LINE__);
#endif
- merge_file->fd = innobase_mysql_tmpfile();
- merge_file->offset = 0;
- merge_file->n_rec = 0;
+ fd = innobase_mysql_tmpfile();
#ifdef UNIV_PFS_IO
- register_pfs_file_open_end(locker, merge_file->fd);
+ register_pfs_file_open_end(locker, fd);
#endif
+ return(fd);
}
-
/*********************************************************************//**
-Destroy a merge file. */
+Create a merge file. */
static
void
-row_merge_file_destroy(
-/*===================*/
+row_merge_file_create(
+/*==================*/
merge_file_t* merge_file) /*!< out: merge file structure */
{
+ merge_file->fd = row_merge_file_create_low();
+ merge_file->offset = 0;
+ merge_file->n_rec = 0;
+}
+
+/*********************************************************************//**
+Destroy a merge file. And de-register the file from Performance Schema
+if UNIV_PFS_IO is defined. */
+UNIV_INLINE
+void
+row_merge_file_destroy_low(
+/*=======================*/
+ int fd) /*!< in: merge file descriptor */
+{
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_io_begin(&state, locker, merge_file->fd, 0, PSI_FILE_CLOSE,
+ register_pfs_file_io_begin(&state, locker,
+ fd, 0, PSI_FILE_CLOSE,
__FILE__, __LINE__);
#endif
- if (merge_file->fd != -1) {
- close(merge_file->fd);
- merge_file->fd = -1;
- }
-
+ close(fd);
#ifdef UNIV_PFS_IO
register_pfs_file_io_end(locker, 0);
#endif
}
+/*********************************************************************//**
+Destroy a merge file. */
+static
+void
+row_merge_file_destroy(
+/*===================*/
+ merge_file_t* merge_file) /*!< out: merge file structure */
+{
+ if (merge_file->fd != -1) {
+ row_merge_file_destroy_low(merge_file->fd);
+ merge_file->fd = -1;
+ }
+}
/*********************************************************************//**
Determine the precise type of a column that is added to a tem
@@ -2600,7 +2624,7 @@ row_merge_build_indexes(
row_merge_file_create(&merge_files[i]);
}
- tmpfd = innobase_mysql_tmpfile();
+ tmpfd = row_merge_file_create_low();
/* Reset the MySQL row buffer that is used when reporting
duplicate keys. */
@@ -2642,7 +2666,7 @@ row_merge_build_indexes(
}
func_exit:
- close(tmpfd);
+ row_merge_file_destroy_low(tmpfd);
for (i = 0; i < n_indexes; i++) {
row_merge_file_destroy(&merge_files[i]);
=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c 2010-12-28 05:03:45 +0000
+++ b/storage/innobase/row/row0upd.c 2011-01-26 08:02:52 +0000
@@ -1252,6 +1252,10 @@ row_upd_changes_ord_field_binary(
|| dfield_is_null(dfield)) {
/* do nothing special */
} else if (UNIV_LIKELY_NULL(ext)) {
+ /* Silence a compiler warning without
+ silencing a Valgrind error. */
+ dfield_len = 0;
+ UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len);
/* See if the column is stored externally. */
buf = row_ext_lookup(ext, col_no, &dfield_len);
=== modified file 'storage/innobase/row/row0vers.c'
--- a/storage/innobase/row/row0vers.c 2010-10-01 13:36:35 +0000
+++ b/storage/innobase/row/row0vers.c 2011-01-25 10:35:35 +0000
@@ -669,11 +669,15 @@ row_vers_build_for_semi_consistent_read(
mutex_enter(&kernel_mutex);
version_trx = trx_get_on_id(version_trx_id);
+ if (version_trx
+ && (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY
+ || version_trx->conc_state == TRX_NOT_STARTED)) {
+
+ version_trx = NULL;
+ }
mutex_exit(&kernel_mutex);
- if (!version_trx
- || version_trx->conc_state == TRX_NOT_STARTED
- || version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
+ if (!version_trx) {
/* We found a version that belongs to a
committed transaction: return it. */
=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c 2011-01-06 10:41:30 +0000
+++ b/storage/innobase/srv/srv0srv.c 2011-01-15 07:24:47 +0000
@@ -275,6 +275,11 @@ UNIV_INTERN ulong srv_purge_batch_size =
/* variable counts amount of data read in total (in bytes) */
UNIV_INTERN ulint srv_data_read = 0;
+/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
+NULL value when collecting statistics. By default, it is set to
+SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
+ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
+
/* here we count the amount of data written in total (in bytes) */
UNIV_INTERN ulint srv_data_written = 0;
=== modified file 'storage/innobase/sync/sync0arr.c'
--- a/storage/innobase/sync/sync0arr.c 2010-12-03 07:35:53 +0000
+++ b/storage/innobase/sync/sync0arr.c 2011-01-18 10:30:33 +0000
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -714,7 +714,7 @@ print:
fprintf(stderr, "rw-lock %p ",
(void*) lock);
sync_array_cell_print(stderr, cell);
- rw_lock_debug_print(debug);
+ rw_lock_debug_print(stderr, debug);
return(TRUE);
}
}
=== modified file 'storage/innobase/sync/sync0rw.c'
--- a/storage/innobase/sync/sync0rw.c 2010-11-11 10:22:27 +0000
+++ b/storage/innobase/sync/sync0rw.c 2011-01-18 10:30:33 +0000
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -936,7 +936,7 @@ rw_lock_list_print_info(
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
- rw_lock_debug_print(info);
+ rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
}
@@ -984,7 +984,7 @@ rw_lock_print(
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
- rw_lock_debug_print(info);
+ rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
}
@@ -996,28 +996,29 @@ UNIV_INTERN
void
rw_lock_debug_print(
/*================*/
+ FILE* f, /*!< in: output stream */
rw_lock_debug_t* info) /*!< in: debug struct */
{
ulint rwt;
rwt = info->lock_type;
- fprintf(stderr, "Locked: thread %lu file %s line %lu ",
+ fprintf(f, "Locked: thread %lu file %s line %lu ",
(ulong) os_thread_pf(info->thread_id), info->file_name,
(ulong) info->line);
if (rwt == RW_LOCK_SHARED) {
- fputs("S-LOCK", stderr);
+ fputs("S-LOCK", f);
} else if (rwt == RW_LOCK_EX) {
- fputs("X-LOCK", stderr);
+ fputs("X-LOCK", f);
} else if (rwt == RW_LOCK_WAIT_EX) {
- fputs("WAIT X-LOCK", stderr);
+ fputs("WAIT X-LOCK", f);
} else {
ut_error;
}
if (info->pass != 0) {
- fprintf(stderr, " pass value %lu", (ulong) info->pass);
+ fprintf(f, " pass value %lu", (ulong) info->pass);
}
- putc('\n', stderr);
+ putc('\n', f);
}
/***************************************************************//**
=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c 2010-10-20 11:46:28 +0000
+++ b/storage/innobase/sync/sync0sync.c 2011-01-25 22:33:59 +0000
@@ -222,21 +222,40 @@ UNIV_INTERN mysql_pfs_key_t mutex_list_m
UNIV_INTERN ibool sync_order_checks_on = FALSE;
#endif /* UNIV_SYNC_DEBUG */
+/** Number of slots reserved for each OS thread in the sync level array */
+static const ulint SYNC_THREAD_N_LEVELS = 10000;
+
+typedef struct sync_arr_struct sync_arr_t;
+
+/** Array for tracking sync levels per thread. */
+struct sync_arr_struct {
+ ulint in_use; /*!< Number of active cells */
+ ulint n_elems; /*!< Number of elements in the array */
+ ulint max_elems; /*!< Maximum elements */
+ ulint next_free; /*!< ULINT_UNDEFINED or index of next
+ free slot */
+ sync_level_t* elems; /*!< Array elements */
+};
+
/** Mutexes or rw-locks held by a thread */
struct sync_thread_struct{
- os_thread_id_t id; /*!< OS thread id */
- sync_level_t* levels; /*!< level array for this thread; if
- this is NULL this slot is unused */
+ os_thread_id_t id; /*!< OS thread id */
+ sync_arr_t* levels; /*!< level array for this thread; if
+ this is NULL this slot is unused */
};
-/** Number of slots reserved for each OS thread in the sync level array */
-#define SYNC_THREAD_N_LEVELS 10000
-
/** An acquired mutex or rw-lock and its level in the latching order */
struct sync_level_struct{
- void* latch; /*!< pointer to a mutex or an rw-lock; NULL means that
- the slot is empty */
- ulint level; /*!< level of the latch in the latching order */
+ void* latch; /*!< pointer to a mutex or an
+ rw-lock; NULL means that
+ the slot is empty */
+ ulint level; /*!< level of the latch in the
+ latching order. This field is
+ overloaded to serve as a node in a
+ linked list of free nodes too. When
+ latch == NULL then this will contain
+ the ordinal value of the next free
+ element */
};
/******************************************************************//**
@@ -745,27 +764,28 @@ mutex_n_reserved(void)
/*==================*/
{
mutex_t* mutex;
- ulint count = 0;
+ ulint count = 0;
mutex_enter(&mutex_list_mutex);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+ for (mutex = UT_LIST_GET_FIRST(mutex_list);
+ mutex != NULL;
+ mutex = UT_LIST_GET_NEXT(list, mutex)) {
- while (mutex != NULL) {
if (mutex_get_lock_word(mutex) != 0) {
count++;
}
-
- mutex = UT_LIST_GET_NEXT(list, mutex);
}
mutex_exit(&mutex_list_mutex);
ut_a(count >= 1);
- return(count - 1); /* Subtract one, because this function itself
- was holding one mutex (mutex_list_mutex) */
+ /* Subtract one, because this function itself was holding
+ one mutex (mutex_list_mutex) */
+
+ return(count - 1);
}
/******************************************************************//**
@@ -781,20 +801,6 @@ sync_all_freed(void)
}
/******************************************************************//**
-Gets the value in the nth slot in the thread level arrays.
-@return pointer to thread slot */
-static
-sync_thread_t*
-sync_thread_level_arrays_get_nth(
-/*=============================*/
- ulint n) /*!< in: slot number */
-{
- ut_ad(n < OS_THREAD_MAX_N);
-
- return(sync_thread_level_arrays + n);
-}
-
-/******************************************************************//**
Looks for the thread slot for the calling thread.
@return pointer to thread slot, NULL if not found */
static
@@ -803,15 +809,15 @@ sync_thread_level_arrays_find_slot(void)
/*====================================*/
{
- sync_thread_t* slot;
- os_thread_id_t id;
ulint i;
+ os_thread_id_t id;
id = os_thread_get_curr_id();
for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
- slot = sync_thread_level_arrays_get_nth(i);
+ slot = &sync_thread_level_arrays[i];
if (slot->levels && os_thread_eq(slot->id, id)) {
@@ -831,12 +837,12 @@ sync_thread_level_arrays_find_free(void)
/*====================================*/
{
- sync_thread_t* slot;
ulint i;
for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
- slot = sync_thread_level_arrays_get_nth(i);
+ slot = &sync_thread_level_arrays[i];
if (slot->levels == NULL) {
@@ -848,19 +854,44 @@ sync_thread_level_arrays_find_free(void)
}
/******************************************************************//**
-Gets the value in the nth slot in the thread level array.
-@return pointer to level slot */
+Print warning. */
static
-sync_level_t*
-sync_thread_levels_get_nth(
-/*=======================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
- thread */
- ulint n) /*!< in: slot number */
+void
+sync_print_warning(
+/*===============*/
+ const sync_level_t* slot) /*!< in: slot for which to
+ print warning */
{
- ut_ad(n < SYNC_THREAD_N_LEVELS);
+ mutex_t* mutex;
+
+ mutex = slot->latch;
- return(arr + n);
+ if (mutex->magic_n == MUTEX_MAGIC_N) {
+ fprintf(stderr,
+ "Mutex created at %s %lu\n",
+ mutex->cfile_name, (ulong) mutex->cline);
+
+ if (mutex_get_lock_word(mutex) != 0) {
+ ulint line;
+ const char* file_name;
+ os_thread_id_t thread_id;
+
+ mutex_get_debug_info(
+ mutex, &file_name, &line, &thread_id);
+
+ fprintf(stderr,
+ "InnoDB: Locked mutex:"
+ " addr %p thread %ld file %s line %ld\n",
+ (void*) mutex, os_thread_pf(thread_id),
+ file_name, (ulong) line);
+ } else {
+ fputs("Not locked\n", stderr);
+ }
+ } else {
+ rw_lock_t* lock = slot->latch;
+
+ rw_lock_print(lock);
+ }
}
/******************************************************************//**
@@ -871,69 +902,29 @@ static
ibool
sync_thread_levels_g(
/*=================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
+ sync_arr_t* arr, /*!< in: pointer to level array for an OS
thread */
ulint limit, /*!< in: level limit */
ulint warn) /*!< in: TRUE=display a diagnostic message */
{
- sync_level_t* slot;
- rw_lock_t* lock;
- mutex_t* mutex;
ulint i;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
-
- slot = sync_thread_levels_get_nth(arr, i);
-
- if (slot->latch != NULL) {
- if (slot->level <= limit) {
+ for (i = 0; i < arr->n_elems; i++) {
+ const sync_level_t* slot;
- if (!warn) {
-
- return(FALSE);
- }
-
- lock = slot->latch;
- mutex = slot->latch;
+ slot = &arr->elems[i];
+ if (slot->latch != NULL && slot->level <= limit) {
+ if (warn) {
fprintf(stderr,
"InnoDB: sync levels should be"
" > %lu but a level is %lu\n",
(ulong) limit, (ulong) slot->level);
- if (mutex->magic_n == MUTEX_MAGIC_N) {
- fprintf(stderr,
- "Mutex created at %s %lu\n",
- mutex->cfile_name,
- (ulong) mutex->cline);
-
- if (mutex_get_lock_word(mutex) != 0) {
- const char* file_name;
- ulint line;
- os_thread_id_t thread_id;
-
- mutex_get_debug_info(
- mutex, &file_name,
- &line, &thread_id);
-
- fprintf(stderr,
- "InnoDB: Locked mutex:"
- " addr %p thread %ld"
- " file %s line %ld\n",
- (void*) mutex,
- os_thread_pf(
- thread_id),
- file_name,
- (ulong) line);
- } else {
- fputs("Not locked\n", stderr);
- }
- } else {
- rw_lock_print(lock);
- }
-
- return(FALSE);
+ sync_print_warning(slot);
}
+
+ return(FALSE);
}
}
@@ -942,31 +933,29 @@ sync_thread_levels_g(
/******************************************************************//**
Checks if the level value is stored in the level array.
-@return TRUE if stored */
+@return slot if found or NULL */
static
-ibool
+const sync_level_t*
sync_thread_levels_contain(
/*=======================*/
- sync_level_t* arr, /*!< in: pointer to level array for an OS
+ sync_arr_t* arr, /*!< in: pointer to level array for an OS
thread */
ulint level) /*!< in: level */
{
- sync_level_t* slot;
ulint i;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; i++) {
+ const sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
- if (slot->latch != NULL) {
- if (slot->level == level) {
+ if (slot->latch != NULL && slot->level == level) {
- return(TRUE);
- }
+ return(slot);
}
}
- return(FALSE);
+ return(NULL);
}
/******************************************************************//**
@@ -980,10 +969,9 @@ sync_thread_levels_contains(
ulint level) /*!< in: latching order level
(SYNC_DICT, ...)*/
{
- sync_level_t* arr;
- sync_thread_t* thread_slot;
- sync_level_t* slot;
ulint i;
+ sync_arr_t* arr;
+ sync_thread_t* thread_slot;
if (!sync_order_checks_on) {
@@ -1003,9 +991,10 @@ sync_thread_levels_contains(
arr = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; i++) {
+ sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
if (slot->latch != NULL && slot->level == level) {
@@ -1031,10 +1020,9 @@ sync_thread_levels_nonempty_gen(
also purge_is_running mutex is
allowed */
{
- sync_level_t* arr;
- sync_thread_t* thread_slot;
- sync_level_t* slot;
ulint i;
+ sync_arr_t* arr;
+ sync_thread_t* thread_slot;
if (!sync_order_checks_on) {
@@ -1054,9 +1042,10 @@ sync_thread_levels_nonempty_gen(
arr = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < arr->n_elems; ++i) {
+ const sync_level_t* slot;
- slot = sync_thread_levels_get_nth(arr, i);
+ slot = &arr->elems[i];
if (slot->latch != NULL
&& (!dict_mutex_allowed
@@ -1098,10 +1087,10 @@ sync_thread_add_level(
ulint level) /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
{
- sync_level_t* array;
+ ulint i;
sync_level_t* slot;
+ sync_arr_t* array;
sync_thread_t* thread_slot;
- ulint i;
if (!sync_order_checks_on) {
@@ -1126,20 +1115,23 @@ sync_thread_add_level(
thread_slot = sync_thread_level_arrays_find_slot();
if (thread_slot == NULL) {
- /* We have to allocate the level array for a new thread */
- array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS);
+ ulint sz;
- thread_slot = sync_thread_level_arrays_find_free();
+ sz = sizeof(*array)
+ + (sizeof(*array->elems) * SYNC_THREAD_N_LEVELS);
- thread_slot->id = os_thread_get_curr_id();
- thread_slot->levels = array;
+ /* We have to allocate the level array for a new thread */
+ array = calloc(sz, sizeof(char));
+ ut_a(array != NULL);
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ array->next_free = ULINT_UNDEFINED;
+ array->max_elems = SYNC_THREAD_N_LEVELS;
+ array->elems = (sync_level_t*) &array[1];
- slot = sync_thread_levels_get_nth(array, i);
+ thread_slot = sync_thread_level_arrays_find_free();
- slot->latch = NULL;
- }
+ thread_slot->levels = array;
+ thread_slot->id = os_thread_get_curr_id();
}
array = thread_slot->levels;
@@ -1303,19 +1295,26 @@ sync_thread_add_level(
ut_error;
}
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ if (array->next_free == ULINT_UNDEFINED) {
+ ut_a(array->n_elems < array->max_elems);
- slot = sync_thread_levels_get_nth(array, i);
+ i = array->n_elems++;
+ } else {
+ i = array->next_free;
+ array->next_free = array->elems[i].level;
+ }
- if (slot->latch == NULL) {
- slot->latch = latch;
- slot->level = level;
+ ut_a(i < array->n_elems);
+ ut_a(i != ULINT_UNDEFINED);
- break;
- }
- }
+ ++array->in_use;
- ut_a(i < SYNC_THREAD_N_LEVELS);
+ slot = &array->elems[i];
+
+ ut_a(slot->latch == NULL);
+
+ slot->latch = latch;
+ slot->level = level;
mutex_exit(&sync_thread_mutex);
}
@@ -1331,8 +1330,7 @@ sync_thread_reset_level(
/*====================*/
void* latch) /*!< in: pointer to a mutex or an rw-lock */
{
- sync_level_t* array;
- sync_level_t* slot;
+ sync_arr_t* array;
sync_thread_t* thread_slot;
ulint i;
@@ -1363,17 +1361,37 @@ sync_thread_reset_level(
array = thread_slot->levels;
- for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
+ for (i = 0; i < array->n_elems; i++) {
+ sync_level_t* slot;
- slot = sync_thread_levels_get_nth(array, i);
+ slot = &array->elems[i];
- if (slot->latch == latch) {
- slot->latch = NULL;
+ if (slot->latch != latch) {
+ continue;
+ }
- mutex_exit(&sync_thread_mutex);
+ slot->latch = NULL;
- return(TRUE);
+ /* Update the free slot list. See comment in sync_level_t
+ for the level field. */
+ slot->level = array->next_free;
+ array->next_free = i;
+
+ ut_a(array->in_use >= 1);
+ --array->in_use;
+
+ /* If all cells are idle then reset the free
+ list. The assumption is that this will save
+ time when we need to scan up to n_elems. */
+
+ if (array->in_use == 0) {
+ array->n_elems = 0;
+ array->next_free = ULINT_UNDEFINED;
}
+
+ mutex_exit(&sync_thread_mutex);
+
+ return(TRUE);
}
if (((mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) {
@@ -1403,11 +1421,6 @@ void
sync_init(void)
/*===========*/
{
-#ifdef UNIV_SYNC_DEBUG
- sync_thread_t* thread_slot;
- ulint i;
-#endif /* UNIV_SYNC_DEBUG */
-
ut_a(sync_initialized == FALSE);
sync_initialized = TRUE;
@@ -1421,13 +1434,10 @@ sync_init(void)
/* Create the thread latch level array where the latch levels
are stored for each OS thread */
- sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N
- * sizeof(sync_thread_t));
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_level_arrays = calloc(
+ sizeof(sync_thread_t), OS_THREAD_MAX_N);
+ ut_a(sync_thread_level_arrays != NULL);
- thread_slot = sync_thread_level_arrays_get_nth(i);
- thread_slot->levels = NULL;
- }
#endif /* UNIV_SYNC_DEBUG */
/* Init the mutex list and create the mutex to protect it. */
@@ -1454,6 +1464,34 @@ sync_init(void)
#endif /* UNIV_SYNC_DEBUG */
}
+#ifdef UNIV_SYNC_DEBUG
+/******************************************************************//**
+Frees all debug memory. */
+static
+void
+sync_thread_level_arrays_free(void)
+/*===============================*/
+
+{
+ ulint i;
+
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ sync_thread_t* slot;
+
+ slot = &sync_thread_level_arrays[i];
+
+ /* If this slot was allocated then free the slot memory too. */
+ if (slot->levels != NULL) {
+ free(slot->levels);
+ slot->levels = NULL;
+ }
+ }
+
+ free(sync_thread_level_arrays);
+ sync_thread_level_arrays = NULL;
+}
+#endif /* UNIV_SYNC_DEBUG */
+
/******************************************************************//**
Frees the resources in InnoDB's own synchronization data structures. Use
os_sync_free() after calling this. */
@@ -1466,17 +1504,20 @@ sync_close(void)
sync_array_free(sync_primary_wait_array);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+ for (mutex = UT_LIST_GET_FIRST(mutex_list);
+ mutex != NULL;
+ /* No op */) {
- while (mutex) {
#ifdef UNIV_MEM_DEBUG
if (mutex == &mem_hash_mutex) {
mutex = UT_LIST_GET_NEXT(list, mutex);
continue;
}
#endif /* UNIV_MEM_DEBUG */
+
mutex_free(mutex);
- mutex = UT_LIST_GET_FIRST(mutex_list);
+
+ mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
@@ -1485,6 +1526,8 @@ sync_close(void)
/* Switch latching order checks on in sync0sync.c */
sync_order_checks_on = FALSE;
+
+ sync_thread_level_arrays_free();
#endif /* UNIV_SYNC_DEBUG */
sync_initialized = FALSE;
=== modified file 'storage/innobase/trx/trx0trx.c'
--- a/storage/innobase/trx/trx0trx.c 2010-10-27 01:45:58 +0000
+++ b/storage/innobase/trx/trx0trx.c 2011-01-27 11:30:59 +0000
@@ -2004,18 +2004,18 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t*
trx_get_trx_by_xid(
/*===============*/
- XID* xid) /*!< in: X/Open XA transaction identification */
+ const XID* xid) /*!< in: X/Open XA transaction identifier */
{
trx_t* trx;
if (xid == NULL) {
- return (NULL);
+ return(NULL);
}
mutex_enter(&kernel_mutex);
@@ -2028,10 +2028,16 @@ trx_get_trx_by_xid(
of gtrid_length+bqual_length bytes should be
the same */
- if (xid->gtrid_length == trx->xid.gtrid_length
+ if (trx->conc_state == TRX_PREPARED
+ && xid->gtrid_length == trx->xid.gtrid_length
&& xid->bqual_length == trx->xid.bqual_length
&& memcmp(xid->data, trx->xid.data,
xid->gtrid_length + xid->bqual_length) == 0) {
+
+ /* Invalidate the XID, so that subsequent calls
+ will not find it. */
+ memset(&trx->xid, 0, sizeof(trx->xid));
+ trx->xid.formatID = -1;
break;
}
@@ -2040,14 +2046,5 @@ trx_get_trx_by_xid(
mutex_exit(&kernel_mutex);
- if (trx) {
- if (trx->conc_state != TRX_PREPARED) {
-
- return(NULL);
- }
-
- return(trx);
- } else {
- return(NULL);
- }
+ return(trx);
}
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-5.5-mtr branch (bjorn.munch:3162 to 3164) | Bjorn Munch | 4 Feb |