From: Martin Hansson Date: May 11 2011 1:06pm Subject: bzr push into mysql-trunk branch (martin.hansson:3368 to 3369) WL#5874 List-Archive: http://lists.mysql.com/commits/137077 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1887546334==" --===============1887546334== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3369 Martin Hansson 2011-05-11 Wl#5874 Done: - Memory leak fixed. - An extra constructor added for the UPDATE part of INSERT ON DUPLICATE KEY. - COPY_INFO statistics moved to their own nested class. Lets us use a default constructor and shorten COPY_INFO's initializer lists. Not done: - REPLACE INTO is not yet done and tests for it are missing. - At Tor's behest, all arguments taken by reference must be changed to taking them by pointers. - Lots of now-dead code must be deleted. Most notably the Field_timestamp pointers in TABLE and TABLE_SHARE, and Field_timestamp::set_time(). - We need to test backward compatibility for .frm files. removed: mysql-test/r/wl5874.result mysql-test/t/wl5874.test added: mysql-test/r/function_defaults.result mysql-test/t/function_defaults.test modified: new_files.txt sql/sql_class.cc sql/sql_class.h sql/sql_insert.cc sql/sql_load.cc sql/table.cc unittest/gunit/copy_info-t.cc 3368 Martin Hansson 2011-05-10 Wl#5874 All tests pass, but some more remains to be done. - Fatal memory leak in COPY_INFO. Hopefully this can be remedied by freeing the memory in the destructor, but it must be verified that it is always called. (In MySQL code we cannot take this for granted). - REPLACE INTO is not yet done and tests for it are missing. - At Tor's behest, all arguments taken by reference must be changed to taking them by pointers. - Lots of now-dead code must be deleted. Most notably the Field_timestamp pointers in TABLE and TABLE_SHARE, and Field_timestamp::set_time(). - We need to test backward compatibility for .frm files. added: mysql-test/r/wl5874.result mysql-test/t/wl5874.test new_files.txt unittest/gunit/copy_info-t.cc unittest/gunit/create_field-t.cc unittest/gunit/field_timestamp-t.cc unittest/gunit/item_func_now_local-t.cc unittest/gunit/mock_field_timestamp.h unittest/gunit/servertest.h modified: .bzr-mysql/default.conf mysql-test/r/create.result mysql-test/r/type_timestamp.result mysql-test/t/create.test mysql-test/t/type_timestamp.test sql/event_db_repository.cc sql/field.cc sql/field.h sql/ha_ndbcluster.cc sql/ha_partition.cc sql/item_timefunc.cc sql/item_timefunc.h sql/sp_head.cc sql/sql_class.cc sql/sql_class.h sql/sql_insert.cc sql/sql_insert.h sql/sql_list.h sql/sql_load.cc sql/sql_parse.cc sql/sql_show.cc sql/sql_table.cc sql/sql_table.h sql/sql_update.cc sql/table.cc sql/table.h sql/unireg.cc storage/archive/ha_archive.cc storage/csv/ha_tina.cc storage/example/ha_example.cc storage/federated/ha_federated.cc storage/heap/ha_heap.cc storage/innobase/handler/ha_innodb.cc storage/myisam/ha_myisam.cc storage/myisammrg/ha_myisammrg.cc unittest/gunit/CMakeLists.txt === added file 'mysql-test/r/function_defaults.result' --- a/mysql-test/r/function_defaults.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/function_defaults.result 2011-05-11 13:05:53 +0000 @@ -0,0 +1,256 @@ +# +# Worklog#5874: +# +# +SET TIME_ZONE = "+00:00"; +CREATE TABLE t1 ( +a TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +f INT +); +# 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722; +INSERT INTO t1 ( f ) VALUES (1); +SELECT * FROM t1; +a b c d e f +2011-04-19 07:22:02 2011-04-19 07:22:02 2011-04-19 07:22:02 0000-00-00 00:00:00 0000-00-00 00:00:00 1 +# 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798; +UPDATE t1 SET f = 2; +SELECT * FROM t1; +a b c d e f +2011-04-19 07:23:18 2011-04-19 07:23:18 2011-04-19 07:22:02 2011-04-19 07:23:18 2011-04-19 07:23:18 2 +DROP TABLE t1; +# +# Test of ON DUPLICATE KEY +# +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP ); +INSERT INTO t1 VALUES +(1, 0, '2001-01-01 01:01:01'), +(2, 0, '2002-02-02 02:02:02'), +(3, 0, '2003-03-03 03:03:03'); +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 0 2002-02-02 02:02:02 +3 0 2003-03-03 03:03:03 +UPDATE t1 SET b = 2, c = c WHERE a = 2; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 2 2002-02-02 02:02:02 +3 0 2003-03-03 03:03:03 +INSERT INTO t1 (a) VALUES (4); +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 2 2002-02-02 02:02:02 +3 0 2003-03-03 03:03:03 +4 NULL 2011-04-19 07:23:18 +UPDATE t1 SET c = '2004-04-04 04:04:04' WHERE a = 4; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 2 2002-02-02 02:02:02 +3 0 2003-03-03 03:03:03 +4 NULL 2004-04-04 04:04:04 +INSERT INTO t1 (a) VALUES (3), (5) ON DUPLICATE KEY UPDATE b = 3, c = c; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 2 2002-02-02 02:02:02 +3 3 2003-03-03 03:03:03 +4 NULL 2004-04-04 04:04:04 +5 NULL 2011-04-19 07:23:18 +INSERT INTO t1 (a, c) VALUES +(4, '2004-04-04 00:00:00'), +(6, '2006-06-06 06:06:06') +ON DUPLICATE KEY UPDATE b = 4; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01 +2 2 2002-02-02 02:02:02 +3 3 2003-03-03 03:03:03 +4 4 2011-04-19 07:23:18 +5 NULL 2011-04-19 07:23:18 +6 NULL 2006-06-06 06:06:06 +DROP TABLE t1; +# +# Test of INSERT DELAYED ... SET ... +# +# 2011-04-19 08:02:40 UTC +SET TIMESTAMP = 1303200160; +CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); +INSERT DELAYED INTO t1 SET a = 1; +FLUSH TABLE t1; +SELECT * FROM t1; +a tmsp +1 2011-04-19 08:02:40 +SELECT * FROM t1 WHERE tmsp = 0; +a tmsp +INSERT DELAYED INTO t1 SET a = 2, tmsp = '1980-01-02 10:20:30'; +FLUSH TABLE t1; +SELECT * FROM t1; +a tmsp +1 2011-04-19 08:02:40 +2 1980-01-02 10:20:30 +DROP TABLE t1; +# +# Test of INSERT DELAYED ... VALUES ... +# +# 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241; +CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); +INSERT DELAYED INTO t1 ( a ) VALUES (1); +FLUSH TABLE t1; +SELECT * FROM t1; +a tmsp +1 2011-04-19 08:04:01 +INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56'); +FLUSH TABLE t1; +SELECT * FROM t1; +a tmsp +1 2011-04-19 08:04:01 +2 1977-12-19 12:34:56 +DROP TABLE t1; +# 2011-04-20 07:05:39 UTC +SET TIMESTAMP = 1303283139; +CREATE TABLE t1 ( +a TIMESTAMP DEFAULT "2010-10-11 12:34:56", +b DATETIME DEFAULT "2010-10-11 12:34:56" +); +INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT); +INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT); +SELECT * FROM t1; +a b +2011-04-20 07:05:39 NULL +2010-10-11 12:34:56 2010-10-11 12:34:56 +2011-04-20 07:05:39 NULL +2010-10-11 12:34:56 2010-10-11 12:34:56 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +b DATETIME DEFAULT CURRENT_TIMESTAMP, +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221; +INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2); +INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 NULL 1 +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +2011-04-20 09:53:41 NULL 3 +2011-04-20 09:53:41 2011-04-20 09:53:41 4 +SET TIME_ZONE = "+03:00"; +SELECT * FROM t1; +a b c +2011-04-20 12:53:41 NULL 1 +2011-04-20 12:53:41 2011-04-20 09:53:41 2 +2011-04-20 12:53:41 NULL 3 +2011-04-20 12:53:41 2011-04-20 09:53:41 4 +SET TIME_ZONE = "+00:00"; +DELETE FROM t1; +INSERT INTO t1 ( c ) VALUES (1); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 1 +# 2011-04-20 17:06:13 +SET TIMESTAMP = 1303311973; +UPDATE t1 t11, t1 t12 SET t11.c = 1; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 1 +UPDATE t1 t11, t1 t12 SET t11.c = 2; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b DATETIME ON UPDATE CURRENT_TIMESTAMP, +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221; +INSERT INTO t1 ( c ) VALUES ( 1 ); +SELECT * FROM t1; +a b c +0000-00-00 00:00:00 NULL 1 +UPDATE t1 SET c = 1; +SELECT * FROM t1; +a b c +0000-00-00 00:00:00 NULL 1 +UPDATE t1 SET c = 2; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +# 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973; +UPDATE t1 t11, t1 t12 SET t11.c = 2; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; +a b c +2011-04-20 15:06:13 2011-04-20 15:06:13 3 +DROP TABLE t1; +# +# Test of CREATE TABLE ... SELECT ... +# +CREATE TABLE t1 ( +a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +b TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +d DATETIME DEFAULT CURRENT_TIMESTAMP, +e DATETIME ON UPDATE CURRENT_TIMESTAMP, +f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE TABLE t2 SELECT a, b, c, d, e, f FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `d` datetime DEFAULT NULL, + `e` datetime DEFAULT NULL, + `f` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; +# +# Test of ALTER TABLE, reordering columns. +# +CREATE TABLE t1 ( a TIMESTAMP, b INT ); +ALTER TABLE t1 MODIFY a TIMESTAMP AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) DEFAULT NULL, + `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a INT, b TIMESTAMP, c TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `a` int(11) DEFAULT NULL, + `c` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a INT, b TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; === removed file 'mysql-test/r/wl5874.result' --- a/mysql-test/r/wl5874.result 2011-05-10 14:18:34 +0000 +++ b/mysql-test/r/wl5874.result 1970-01-01 00:00:00 +0000 @@ -1,202 +0,0 @@ -# -# Worklog#5874: -# -# -SET TIME_ZONE = "+00:00"; -CREATE TABLE t2 ( -a TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -b TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -c TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -d TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -e TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -f INT -); -# 2011-04-19 07:22:02 UTC -SET TIMESTAMP = 1303197722; -INSERT INTO t2 ( f ) VALUES (1); -SELECT * FROM t2; -a b c d e f -2011-04-19 07:22:02 2011-04-19 07:22:02 2011-04-19 07:22:02 0000-00-00 00:00:00 0000-00-00 00:00:00 1 -# 2011-04-19 07:23:18 UTC -SET TIMESTAMP = 1303197798; -UPDATE t2 SET f = 2; -SELECT * FROM t2; -a b c d e f -2011-04-19 07:23:18 2011-04-19 07:23:18 2011-04-19 07:22:02 2011-04-19 07:23:18 2011-04-19 07:23:18 2 -DROP TABLE t2; -# -# Test of INSERT DELAYED ... SET ... -# -# 2011-04-19 08:02:40 UTC -SET TIMESTAMP = 1303200160; -CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); -INSERT DELAYED INTO t1 SET a = 1; -FLUSH TABLE t1; -SELECT * FROM t1; -a tmsp -1 2011-04-19 08:02:40 -SELECT * FROM t1 WHERE tmsp = 0; -a tmsp -INSERT DELAYED INTO t1 SET a = 2, tmsp = '1980-01-02 10:20:30'; -FLUSH TABLE t1; -SELECT * FROM t1; -a tmsp -1 2011-04-19 08:02:40 -2 1980-01-02 10:20:30 -DROP TABLE t1; -# -# Test of INSERT DELAYED ... VALUES ... -# -# 2011-04-19 08:04:01 UTC -SET TIMESTAMP = 1303200241; -CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); -INSERT DELAYED INTO t1 ( a ) VALUES (1); -FLUSH TABLE t1; -SELECT * FROM t1; -a tmsp -1 2011-04-19 08:04:01 -INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56'); -FLUSH TABLE t1; -SELECT * FROM t1; -a tmsp -1 2011-04-19 08:04:01 -2 1977-12-19 12:34:56 -DROP TABLE t1; -# 2011-04-20 07:05:39 UTC -SET TIMESTAMP = 1303283139; -CREATE TABLE t1 ( -a TIMESTAMP DEFAULT "2010-10-11 12:34:56", -b DATETIME DEFAULT "2010-10-11 12:34:56" -); -INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT); -INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT); -SELECT * FROM t1; -a b -2011-04-20 07:05:39 NULL -2010-10-11 12:34:56 2010-10-11 12:34:56 -2011-04-20 07:05:39 NULL -2010-10-11 12:34:56 2010-10-11 12:34:56 -DROP TABLE t1; -CREATE TABLE t1 ( -a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -b DATETIME DEFAULT CURRENT_TIMESTAMP, -c INT -); -# 2011-04-20 09:53:41 UTC -SET TIMESTAMP = 1303293221; -INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2); -INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4); -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 NULL 1 -2011-04-20 09:53:41 2011-04-20 09:53:41 2 -2011-04-20 09:53:41 NULL 3 -2011-04-20 09:53:41 2011-04-20 09:53:41 4 -SET TIME_ZONE = "+03:00"; -SELECT * FROM t1; -a b c -2011-04-20 12:53:41 NULL 1 -2011-04-20 12:53:41 2011-04-20 09:53:41 2 -2011-04-20 12:53:41 NULL 3 -2011-04-20 12:53:41 2011-04-20 09:53:41 4 -SET TIME_ZONE = "+00:00"; -DELETE FROM t1; -INSERT INTO t1 ( c ) VALUES (1); -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 1 -# 2011-04-20 17:06:13 -SET TIMESTAMP = 1303311973; -UPDATE t1 t11, t1 t12 SET t11.c = 1; -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 1 -UPDATE t1 t11, t1 t12 SET t11.c = 2; -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 2 -DROP TABLE t1; -CREATE TABLE t1 ( -a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -b DATETIME ON UPDATE CURRENT_TIMESTAMP, -c INT -); -# 2011-04-20 09:53:41 UTC -SET TIMESTAMP = 1303293221; -INSERT INTO t1 ( c ) VALUES ( 1 ); -SELECT * FROM t1; -a b c -0000-00-00 00:00:00 NULL 1 -UPDATE t1 SET c = 1; -SELECT * FROM t1; -a b c -0000-00-00 00:00:00 NULL 1 -UPDATE t1 SET c = 2; -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 2 -# 2011-04-20 15:06:13 UTC -SET TIMESTAMP = 1303311973; -UPDATE t1 t11, t1 t12 SET t11.c = 2; -SELECT * FROM t1; -a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 2 -UPDATE t1 t11, t1 t12 SET t11.c = 3; -SELECT * FROM t1; -a b c -2011-04-20 15:06:13 2011-04-20 15:06:13 3 -DROP TABLE t1; -# -# Test of CREATE TABLE ... SELECT ... -# -CREATE TABLE t1 ( -a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -b TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -c TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -d DATETIME DEFAULT CURRENT_TIMESTAMP, -e DATETIME ON UPDATE CURRENT_TIMESTAMP, -f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); -CREATE TABLE t2 SELECT a, b, c, d, e, f FROM t1; -SHOW CREATE TABLE t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `d` datetime DEFAULT NULL, - `e` datetime DEFAULT NULL, - `f` datetime DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1, t2; -# -# Test of ALTER TABLE, reordering columns. -# -CREATE TABLE t1 ( a TIMESTAMP, b INT ); -ALTER TABLE t1 MODIFY a TIMESTAMP AFTER b; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `b` int(11) DEFAULT NULL, - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1; -CREATE TABLE t1 ( a INT, b TIMESTAMP, c TIMESTAMP NULL ); -ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `a` int(11) DEFAULT NULL, - `c` timestamp NULL DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1; -CREATE TABLE t1 ( a INT, b TIMESTAMP NULL ); -ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `a` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1; === added file 'mysql-test/t/function_defaults.test' --- a/mysql-test/t/function_defaults.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/function_defaults.test 2011-05-11 13:05:53 +0000 @@ -0,0 +1,212 @@ +--echo # +--echo # Worklog#5874: +--echo # +--echo # +SET TIME_ZONE = "+00:00"; + +CREATE TABLE t1 ( + a TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + b TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + c TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + d TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + e TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + f INT +); + +--echo # 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722; + +INSERT INTO t1 ( f ) VALUES (1); +SELECT * FROM t1; + +--echo # 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798; + +UPDATE t1 SET f = 2; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of ON DUPLICATE KEY +--echo # +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP ); + +INSERT INTO t1 VALUES + (1, 0, '2001-01-01 01:01:01'), + (2, 0, '2002-02-02 02:02:02'), + (3, 0, '2003-03-03 03:03:03'); +SELECT * FROM t1; + +UPDATE t1 SET b = 2, c = c WHERE a = 2; +SELECT * FROM t1; + +INSERT INTO t1 (a) VALUES (4); +SELECT * FROM t1; + +UPDATE t1 SET c = '2004-04-04 04:04:04' WHERE a = 4; +SELECT * FROM t1; + +INSERT INTO t1 (a) VALUES (3), (5) ON DUPLICATE KEY UPDATE b = 3, c = c; +SELECT * FROM t1; + +INSERT INTO t1 (a, c) VALUES + (4, '2004-04-04 00:00:00'), + (6, '2006-06-06 06:06:06') +ON DUPLICATE KEY UPDATE b = 4; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of INSERT DELAYED ... SET ... +--echo # + +--echo # 2011-04-19 08:02:40 UTC +SET TIMESTAMP = 1303200160; + +CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); + +INSERT DELAYED INTO t1 SET a = 1; +FLUSH TABLE t1; + +SELECT * FROM t1; +SELECT * FROM t1 WHERE tmsp = 0; + +INSERT DELAYED INTO t1 SET a = 2, tmsp = '1980-01-02 10:20:30'; +FLUSH TABLE t1; + +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of INSERT DELAYED ... VALUES ... +--echo # + +--echo # 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241; + +CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); + +INSERT DELAYED INTO t1 ( a ) VALUES (1); +FLUSH TABLE t1; +SELECT * FROM t1; + +INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56'); +FLUSH TABLE t1; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # 2011-04-20 07:05:39 UTC +SET TIMESTAMP = 1303283139; +CREATE TABLE t1 ( + a TIMESTAMP DEFAULT "2010-10-11 12:34:56", + b DATETIME DEFAULT "2010-10-11 12:34:56" +); + +INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT); +INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT); +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1 ( + a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + b DATETIME DEFAULT CURRENT_TIMESTAMP, + c INT +); + +--echo # 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221; + +INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2); +INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4); +SELECT * FROM t1; + +SET TIME_ZONE = "+03:00"; +SELECT * FROM t1; +SET TIME_ZONE = "+00:00"; + +DELETE FROM t1; + +INSERT INTO t1 ( c ) VALUES (1); +SELECT * FROM t1; + +--echo # 2011-04-20 17:06:13 +SET TIMESTAMP = 1303311973; + +UPDATE t1 t11, t1 t12 SET t11.c = 1; +SELECT * FROM t1; + +UPDATE t1 t11, t1 t12 SET t11.c = 2; + +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1 ( + a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + b DATETIME ON UPDATE CURRENT_TIMESTAMP, + c INT +); + +--echo # 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221; + +INSERT INTO t1 ( c ) VALUES ( 1 ); +SELECT * FROM t1; + +UPDATE t1 SET c = 1; +SELECT * FROM t1; + +UPDATE t1 SET c = 2; +SELECT * FROM t1; + +--echo # 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973; + +UPDATE t1 t11, t1 t12 SET t11.c = 2; +SELECT * FROM t1; + +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of CREATE TABLE ... SELECT ... +--echo # +CREATE TABLE t1 ( + a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + b TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + c TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + d DATETIME DEFAULT CURRENT_TIMESTAMP, + e DATETIME ON UPDATE CURRENT_TIMESTAMP, + f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +CREATE TABLE t2 SELECT a, b, c, d, e, f FROM t1; + +SHOW CREATE TABLE t2; + +DROP TABLE t1, t2; + +--echo # +--echo # Test of ALTER TABLE, reordering columns. +--echo # +CREATE TABLE t1 ( a TIMESTAMP, b INT ); +ALTER TABLE t1 MODIFY a TIMESTAMP AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 ( a INT, b TIMESTAMP, c TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 ( a INT, b TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; === removed file 'mysql-test/t/wl5874.test' --- a/mysql-test/t/wl5874.test 2011-05-10 14:18:34 +0000 +++ b/mysql-test/t/wl5874.test 1970-01-01 00:00:00 +0000 @@ -1,181 +0,0 @@ ---echo # ---echo # Worklog#5874: ---echo # ---echo # -SET TIME_ZONE = "+00:00"; - -CREATE TABLE t2 ( - a TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - b TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - c TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - d TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - e TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - f INT -); - ---echo # 2011-04-19 07:22:02 UTC -SET TIMESTAMP = 1303197722; - -INSERT INTO t2 ( f ) VALUES (1); -SELECT * FROM t2; - ---echo # 2011-04-19 07:23:18 UTC -SET TIMESTAMP = 1303197798; - -UPDATE t2 SET f = 2; -SELECT * FROM t2; - -DROP TABLE t2; - ---echo # ---echo # Test of INSERT DELAYED ... SET ... ---echo # - ---echo # 2011-04-19 08:02:40 UTC -SET TIMESTAMP = 1303200160; - -CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); - -INSERT DELAYED INTO t1 SET a = 1; -FLUSH TABLE t1; - -SELECT * FROM t1; -SELECT * FROM t1 WHERE tmsp = 0; - -INSERT DELAYED INTO t1 SET a = 2, tmsp = '1980-01-02 10:20:30'; -FLUSH TABLE t1; - -SELECT * FROM t1; - -DROP TABLE t1; - ---echo # ---echo # Test of INSERT DELAYED ... VALUES ... ---echo # - ---echo # 2011-04-19 08:04:01 UTC -SET TIMESTAMP = 1303200241; - -CREATE TABLE t1 ( a INT, tmsp TIMESTAMP ); - -INSERT DELAYED INTO t1 ( a ) VALUES (1); -FLUSH TABLE t1; -SELECT * FROM t1; - -INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56'); -FLUSH TABLE t1; -SELECT * FROM t1; - -DROP TABLE t1; - ---echo # 2011-04-20 07:05:39 UTC -SET TIMESTAMP = 1303283139; -CREATE TABLE t1 ( - a TIMESTAMP DEFAULT "2010-10-11 12:34:56", - b DATETIME DEFAULT "2010-10-11 12:34:56" -); - -INSERT INTO t1 VALUES (NULL, NULL), (DEFAULT, DEFAULT); -INSERT INTO t1 ( a, b ) VALUES (NULL, NULL), (DEFAULT, DEFAULT); -SELECT * FROM t1; - -DROP TABLE t1; - -CREATE TABLE t1 ( - a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - b DATETIME DEFAULT CURRENT_TIMESTAMP, - c INT -); - ---echo # 2011-04-20 09:53:41 UTC -SET TIMESTAMP = 1303293221; - -INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2); -INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4); -SELECT * FROM t1; - -SET TIME_ZONE = "+03:00"; -SELECT * FROM t1; -SET TIME_ZONE = "+00:00"; - -DELETE FROM t1; - -INSERT INTO t1 ( c ) VALUES (1); -SELECT * FROM t1; - ---echo # 2011-04-20 17:06:13 -SET TIMESTAMP = 1303311973; - -UPDATE t1 t11, t1 t12 SET t11.c = 1; -SELECT * FROM t1; - -UPDATE t1 t11, t1 t12 SET t11.c = 2; - -SELECT * FROM t1; - -DROP TABLE t1; - -CREATE TABLE t1 ( - a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - b DATETIME ON UPDATE CURRENT_TIMESTAMP, - c INT -); - ---echo # 2011-04-20 09:53:41 UTC -SET TIMESTAMP = 1303293221; - -INSERT INTO t1 ( c ) VALUES ( 1 ); -SELECT * FROM t1; - -UPDATE t1 SET c = 1; -SELECT * FROM t1; - -UPDATE t1 SET c = 2; -SELECT * FROM t1; - ---echo # 2011-04-20 15:06:13 UTC -SET TIMESTAMP = 1303311973; - -UPDATE t1 t11, t1 t12 SET t11.c = 2; -SELECT * FROM t1; - -UPDATE t1 t11, t1 t12 SET t11.c = 3; -SELECT * FROM t1; - -DROP TABLE t1; - ---echo # ---echo # Test of CREATE TABLE ... SELECT ... ---echo # -CREATE TABLE t1 ( - a TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - b TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - c TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - d DATETIME DEFAULT CURRENT_TIMESTAMP, - e DATETIME ON UPDATE CURRENT_TIMESTAMP, - f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); - -CREATE TABLE t2 SELECT a, b, c, d, e, f FROM t1; - -SHOW CREATE TABLE t2; - -DROP TABLE t1, t2; - ---echo # ---echo # Test of ALTER TABLE, reordering columns. ---echo # -CREATE TABLE t1 ( a TIMESTAMP, b INT ); -ALTER TABLE t1 MODIFY a TIMESTAMP AFTER b; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( a INT, b TIMESTAMP, c TIMESTAMP NULL ); -ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( a INT, b TIMESTAMP NULL ); -ALTER TABLE t1 MODIFY b TIMESTAMP FIRST; -SHOW CREATE TABLE t1; -DROP TABLE t1; === modified file 'new_files.txt' --- a/new_files.txt 2011-05-10 14:18:34 +0000 +++ b/new_files.txt 2011-05-11 13:05:53 +0000 @@ -5,5 +5,5 @@ unittest/gunit/item_func_now_local-t.cc unittest/gunit/mock_field_timestamp.h unittest/gunit/servertest.cc unittest/gunit/servertest.h -mysql-test/t/wl5874.test -mysql-test/r/wl5874.result +mysql-test/t/function_defaults.test +mysql-test/r/function_defaults.result === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2011-05-10 14:18:34 +0000 +++ b/sql/sql_class.cc 2011-05-11 13:05:53 +0000 @@ -3885,99 +3885,86 @@ void xid_cache_delete(XID_STATE *xid_sta /** - @param table The modified table. - @param modified_fields List of columns that are modified by the DML + For a certain data changing operation, allocates and calculates a bitmap of + which columns will receive a default value resulting from a function. + + @param table The table whose data changes as a result of performing the + operation. It is assumed that all changed fields belong to this table. + + @param changed_fields List of columns that are modified by the data change statement. This may be NULL, meaning all columns are modified. - The table's MEM_ROOT is used for allocating the bitmap. + @param operation The data change operation to be carried out. + + @retval NULL Memory allocation error. */ MY_BITMAP *get_default_assigned_columns(const TABLE &table, - List *modified_fields, + List *changed_fields, const COPY_INFO &operation) { DBUG_ENTER("get_default_assigned_columns"); - + /* We cannot trust table.s->column_bitmap_size during multi-table UPDATE. */ const uint column_bitmap_size= bitmap_buffer_size(table.s->fields); DBUG_ASSERT(column_bitmap_size > 0); - /* - This lets us handle INSERT DELAYED, where the thread performing the data - change is not the thread executing this function. todo: add unit test - for this - */ - MEM_ROOT *mem_root= table.in_use->mem_root; //operation.get_mem_root(); - - DBUG_PRINT("wl5874_important", ("table @ %p mem_root %p", &table, mem_root)); - - my_bitmap_map *columns_bits= -// (my_bitmap_map*)alloc_root(mem_root, column_bitmap_size); - static_cast(my_malloc(column_bitmap_size, MYF(0))); - if (columns_bits == NULL) - DBUG_RETURN(NULL); - -// MY_BITMAP *columns= (MY_BITMAP*)alloc_root(mem_root, sizeof(MY_BITMAP)); MY_BITMAP *columns= static_cast(my_malloc(sizeof(MY_BITMAP), MYF(0))); if (columns == NULL) DBUG_RETURN(NULL); - DBUG_ASSERT((void*)columns != (void*)columns_bits); + if (bitmap_init(columns, NULL, table.s->fields, FALSE) != 0) + DBUG_RETURN(NULL); - DBUG_ASSERT(table.s->fields > 0); - bitmap_init(columns, columns_bits, table.s->fields, FALSE); + if (changed_fields == NULL) + /* All columns assigned; No defaults set, functions or otherwise. */ + DBUG_RETURN(columns); - /* Find columns with function default on insert. */ + /* Find columns with function default on insert or update. */ for (uint i= 0; i < table.s->fields; ++i) { Field *current_field= table.field[i]; - DBUG_PRINT("wl5874_red", ("Field %s @ %p", - current_field->field_name, - current_field)); + const char *function_default_status = ""; if (operation.get_operation_type() == COPY_INFO::INSERT_OPERATION && current_field->has_insert_default_function()) { - DBUG_PRINT("wl5874_red", ("Field %s has INSERT default function", - current_field->field_name)); + function_default_status = "Has INSERT default function"; bitmap_set_bit(columns, current_field->field_index); } if (operation.get_operation_type() == COPY_INFO::UPDATE_OPERATION && current_field->has_update_default_function()) { - DBUG_PRINT("wl5874_red", ("Field %s has UPDATE default function", - current_field->field_name)); + function_default_status = "Has UPDATE default function"; bitmap_set_bit(columns, current_field->field_index); } + DBUG_PRINT("wl5874_red", ("Field %s @ %p %s", + current_field->field_name, + current_field, + function_default_status)); } - /* Remove explicitly assigned columns. */ - if (modified_fields != NULL) + /* Remove explicitly assigned columns from the bitmap. */ + List_iterator lvalue_it(*changed_fields); + Item *lvalue_item; + while ((lvalue_item= lvalue_it++) != NULL) { - List_iterator lvalue_it(*modified_fields); - Item *lvalue_item; - while ((lvalue_item= lvalue_it++) != NULL) + if (lvalue_item->type() == Item::FIELD_ITEM) { - if (lvalue_item->type() == Item::FIELD_ITEM) + Field *lvalue= static_cast(lvalue_item)->field; + DBUG_ASSERT(lvalue->table == &table); + + if (lvalue != NULL) { - Field *lvalue= static_cast(lvalue_item)->field; - if (lvalue != NULL) - { - DBUG_PRINT("wl5874_red", - ("Field %s is assigned", lvalue->field_name)); - bitmap_clear_bit(columns, lvalue->field_index); - } - else - DBUG_PRINT("wl5874_red", ("Item %s is not resolved!", - lvalue_item->name)); + DBUG_PRINT("wl5874_red", + ("Field %s is assigned", lvalue->field_name)); + bitmap_clear_bit(columns, lvalue->field_index); } + else + DBUG_PRINT("wl5874_red", ("Item %s is not resolved!", + lvalue_item->name)); } } - else - /* - All columns assigned; there can be no defaults, functions or otherwise. - */ - bitmap_clear_all(columns); DBUG_RETURN(columns); } === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2011-05-10 14:18:34 +0000 +++ b/sql/sql_class.h 2011-05-11 13:05:53 +0000 @@ -193,11 +193,27 @@ MY_BITMAP *get_default_assigned_columns( class COPY_INFO { public: + class Statistics + { + public: + Statistics() : + records(0), deleted(0), updated(0), copied(0), error_count(0), touched(0) + {} + + ha_rows records; /**< Number of processed records */ + ha_rows deleted; /**< Number of deleted records */ + ha_rows updated; /**< Number of updated records */ + ha_rows copied; /**< Number of copied records */ + ha_rows error_count; + ha_rows touched; /* Number of touched records */ + }; + enum operation_type { INSERT_OPERATION, UPDATE_OPERATION }; + private: /** Describes the data change operation that this object represents. - */ + */ operation_type m_optype; List *m_inserted_fields; /* const */ bool m_inserts_defaults_only; @@ -205,12 +221,7 @@ private: MY_BITMAP *m_function_default_update_columns; public: - ha_rows records; /**< Number of processed records */ - ha_rows deleted; /**< Number of deleted records */ - ha_rows updated; /**< Number of updated records */ - ha_rows copied; /**< Number of copied records */ - ha_rows error_count; - ha_rows touched; /* Number of touched records */ + Statistics stats; enum enum_duplicates handle_duplicates; int escape_char, last_errno; bool ignore; @@ -220,11 +231,11 @@ public: /* for VIEW ... WITH CHECK OPTION */ TABLE_LIST *view; bool is_select_create; - + /** Initializes this operation as an INSERT that can spawn an UPDATE operation. - + @table_list The parser object representing the table to be modified. @inserted_fields The values to be inserted for the columns. May be NULL, which is interpreted as all columns in the order they appear in the table @@ -237,7 +248,7 @@ public: INSERT operation caused a duplicate key error. @duplicate_handling The policy for handling duplicates. - */ + */ COPY_INFO(operation_type optype, TABLE_LIST *table_list, List *inserted_fields, @@ -250,8 +261,6 @@ public: m_inserts_defaults_only(false), m_function_default_insert_columns(NULL), m_function_default_update_columns(NULL), - records(0), deleted(0), updated(0), copied(0), error_count(0), - touched(0), handle_duplicates(duplicate_handling), escape_char(0), last_errno(0), ignore(ignore_check_option_errors), @@ -262,10 +271,10 @@ public: { DBUG_ASSERT(optype == INSERT_OPERATION); } - - /** + + /** Initializes this data change operation as an INSERT. - + @param all_rows. A list of rows from the INSERT INTO ... VALUES row[, row] construct. MySQL supports the syntax @@ -281,17 +290,16 @@ public: is not allowed. Hence we know that the number of elements in all rows is the same. - */ + */ COPY_INFO(operation_type optype, - List &inserted_fields, - List > &all_rows) : + List *inserted_fields, + List > *all_rows) : m_optype(optype), - m_inserted_fields(&inserted_fields), - m_inserts_defaults_only(all_rows.elements > 0 && - all_rows.head()->elements == 0), + m_inserted_fields(inserted_fields), + m_inserts_defaults_only(all_rows->elements > 0 && + all_rows->head()->elements == 0), m_function_default_insert_columns(NULL), m_function_default_update_columns(NULL), - records(0), deleted(0), updated(0), copied(0), error_count(0), touched(0), handle_duplicates(DUP_ERROR), escape_char(0), last_errno(0), ignore(false), update_fields(NULL), update_values(NULL), view(NULL), is_select_create(false) @@ -300,16 +308,16 @@ public: } - /** - Creates a data change operation where the values to be inserted are not - known at the time of initialization. For instance, the may be read from - a file. - - @param optype The data change opreation type. - @param ignore_duplicates Whether duplicate rows are ignored. - @param duplicates_handling How to handle duplicates. - @param escape_character The escape character. - */ + /** + Creates a data change operation where the values to be inserted are not + known at the time of initialization. For instance, they may be read from + a file. + + @param optype The data change opreation type. + @param ignore_duplicates Whether duplicate rows are ignored. + @param duplicates_handling How to handle duplicates. + @param escape_character The escape character. + */ COPY_INFO(operation_type optype, bool ignore_duplicates, enum_duplicates duplicates_handling, int escape_character) : m_optype(optype), @@ -317,7 +325,6 @@ public: m_inserts_defaults_only(false), m_function_default_insert_columns(NULL), m_function_default_update_columns(NULL), - records(0), deleted(0), updated(0), copied(0), error_count(0), touched(0), handle_duplicates(duplicates_handling), escape_char(escape_character), last_errno(0), ignore(ignore_duplicates), update_fields(NULL), update_values(NULL), view(NULL), @@ -326,28 +333,64 @@ public: DBUG_ASSERT(optype == INSERT_OPERATION); } - /** - Initializes this data change operation as an UPDATE. - @param fields The column objects that are to be updated. - @param values The values to be assigned to the fields. - */ + /** + Initializes a new data change operation as an UPDATE. + @param fields The column objects that are to be updated. + @param values The values to be assigned to the fields. + */ COPY_INFO(operation_type optype, List &fields, List &values) : m_optype(optype), m_inserted_fields(NULL), m_inserts_defaults_only(false), m_function_default_insert_columns(NULL), m_function_default_update_columns(NULL), - records(0), deleted(0), updated(0), copied(0), error_count(0), touched(0), handle_duplicates(DUP_ERROR), escape_char(0), last_errno(0), ignore(false), update_fields(&fields), update_values(&values), view(NULL), - is_select_create(false) { + is_select_create(false) + { + DBUG_ASSERT(optype == UPDATE_OPERATION); + } + + /** + Constructs an UPDATE operation to handle the @c UPDATE part of an INSERT + ON DUPLICATE KEY UPDATE operation. + + @param optype The new operation type, which must be UPDATE_OPERATION. + + @param A COPY_INFO describing an INSERT ON DUPLICATE KEY UPDATE + operation. + */ + COPY_INFO(operation_type optype, const COPY_INFO &insert_update) : + m_optype(optype), + m_inserted_fields(NULL), + m_inserts_defaults_only(false), + m_function_default_insert_columns(NULL), + m_function_default_update_columns(NULL), + stats(insert_update.stats), + handle_duplicates(DUP_ERROR), escape_char(insert_update.escape_char), + last_errno(insert_update.last_errno), ignore(insert_update.ignore), + update_fields(insert_update.update_fields), + update_values(insert_update.update_values), view(NULL), + is_select_create(false) + { DBUG_ASSERT(optype == UPDATE_OPERATION); + DBUG_ASSERT(update_fields != NULL); + DBUG_ASSERT(update_values != NULL); } void set_operation_type(operation_type optype) { m_optype = optype; } operation_type get_operation_type() const { return m_optype; } - List *get_inserted_fields() { return m_inserted_fields; } + /** + Removes any references to statement-local data. + */ + void detach_from_statement() + { + m_inserted_fields= NULL; + update_fields= NULL; + update_values= NULL; + } + bool is_full_row() { @@ -389,9 +432,15 @@ public: ~COPY_INFO() { DBUG_PRINT("wl5874_important", ("~COPY_INFO")); -/* delete m_function_default_insert_columns; - delete m_function_default_update_columns; -*/ + + if (m_function_default_insert_columns != NULL) + bitmap_free(m_function_default_insert_columns); + + if (m_function_default_update_columns != NULL) + bitmap_free(m_function_default_update_columns); + + my_free(m_function_default_insert_columns); + my_free(m_function_default_update_columns); } }; === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2011-05-10 14:18:34 +0000 +++ b/sql/sql_insert.cc 2011-05-11 13:05:53 +0000 @@ -631,7 +631,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t uint value_count; ulong counter = 1; ulonglong id; - COPY_INFO info(COPY_INFO::INSERT_OPERATION, fields, values_list); + COPY_INFO info(COPY_INFO::INSERT_OPERATION, &fields, &values_list); TABLE *table= 0; List_iterator_fast its(values_list); List_item *values; @@ -825,7 +825,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t { if (values_list.elements != 1 && ! thd->is_error()) { - info.records++; + info.stats.records++; continue; } /* @@ -865,7 +865,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t { if (values_list.elements != 1 && ! thd->is_error()) { - info.records++; + info.stats.records++; continue; } error=1; @@ -913,7 +913,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t { if (!error) { - info.copied=values_list.elements; + info.stats.copied=values_list.elements; end_delayed_insert(thd); } } @@ -936,7 +936,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t transactional_table= table->file->has_transactions(); - if ((changed= (info.copied || info.deleted || info.updated))) + if ((changed= (info.stats.copied || info.stats.deleted || info.stats.updated))) { /* Invalidate the table in the query cache if something changed. @@ -1028,7 +1028,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t thd->first_successful_insert_id_in_cur_stmt : (thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : - ((table->next_number_field && info.copied) ? + ((table->next_number_field && info.stats.copied) ? table->next_number_field->val_int() : 0)); table->next_number_field=0; thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -1042,26 +1042,26 @@ bool mysql_insert(THD *thd,TABLE_LIST *t if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) || !thd->cuted_fields)) { - my_ok(thd, info.copied + info.deleted + + my_ok(thd, info.stats.copied + info.stats.deleted + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated), + info.stats.touched : info.stats.updated), id); } else { char buff[160]; ha_rows updated=((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated); + info.stats.touched : info.stats.updated); if (ignore) - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.stats.records, (lock_type == TL_WRITE_DELAYED) ? (ulong) 0 : - (ulong) (info.records - info.copied), + (ulong) (info.stats.records - info.stats.copied), (ulong) thd->warning_info->statement_warn_count()); else - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.deleted + updated), + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.stats.records, + (ulong) (info.stats.deleted + updated), (ulong) thd->warning_info->statement_warn_count()); - ::my_ok(thd, info.copied + info.deleted + updated, id, buff); + ::my_ok(thd, info.stats.copied + info.stats.deleted + updated, id, buff); } thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -1470,7 +1470,7 @@ int write_record(THD *thd, TABLE *table, ulonglong insert_id_for_cur_row= 0; DBUG_ENTER("write_record"); - info->records++; + info->stats.records++; save_read_set= table->read_set; save_write_set= table->write_set; @@ -1559,8 +1559,7 @@ int write_record(THD *thd, TABLE *table, /* This is very elegant, but perhaps a tad inefficient? */ - COPY_INFO update(*info); - update.set_operation_type(COPY_INFO::UPDATE_OPERATION); + COPY_INFO update(COPY_INFO::UPDATE_OPERATION, *info); int res= 0; /* We don't check for other UNIQUE keys - the first row @@ -1570,7 +1569,8 @@ int write_record(THD *thd, TABLE *table, DBUG_ASSERT(table->insert_values != NULL); store_record(table,insert_values); restore_record(table,record[1]); - DBUG_PRINT("wl5874_red", ("update_fields %i", info->update_fields->elements)); + DBUG_PRINT("wl5874_red", ("# update_fields %i", + info->update_fields->elements)); DBUG_ASSERT(info->update_fields->elements == info->update_values->elements); if (fill_record_n_invoke_before_triggers(thd, *info->update_fields, @@ -1592,7 +1592,7 @@ int write_record(THD *thd, TABLE *table, if (table->next_number_field) table->file->adjust_next_insert_id_after_explicit_value( table->next_number_field->val_int()); - info->touched++; + info->stats.touched++; if (!records_are_comparable(table) || compare_records(table)) { DBUG_PRINT("wl5874_red", ("compare records is true")); @@ -1611,7 +1611,7 @@ int write_record(THD *thd, TABLE *table, } if (error != HA_ERR_RECORD_IS_THE_SAME) - info->updated++; + info->stats.updated++; else error= 0; /* @@ -1625,13 +1625,13 @@ int write_record(THD *thd, TABLE *table, trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)); - info->copied++; + info->stats.copied++; } if (table->next_number_field) table->file->adjust_next_insert_id_after_explicit_value( table->next_number_field->val_int()); - info->touched++; + info->stats.touched++; goto ok_or_after_trg_err; } @@ -1664,7 +1664,7 @@ int write_record(THD *thd, TABLE *table, error != HA_ERR_RECORD_IS_THE_SAME) goto err; if (error != HA_ERR_RECORD_IS_THE_SAME) - info->deleted++; + info->stats.deleted++; else error= 0; thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row); @@ -1682,7 +1682,7 @@ int write_record(THD *thd, TABLE *table, goto before_trg_err; if ((error=table->file->ha_delete_row(table->record[1]))) goto err; - info->deleted++; + info->stats.deleted++; if (!table->file->has_transactions()) thd->transaction.stmt.modified_non_trans_table= TRUE; if (table->triggers && @@ -1732,7 +1732,7 @@ int write_record(THD *thd, TABLE *table, } after_trg_n_copied_inc: - info->copied++; + info->stats.copied++; thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row); trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_INSERT, @@ -1924,7 +1924,7 @@ public: } ~Delayed_insert() { - DBUG_PRINT("wl5874_important", ("~Delayed_insert")); + DBUG_ENTER("~Delayed_insert"); /* The following is not really needed, but just for safety */ delayed_row *row; while ((row=rows.get())) @@ -1945,6 +1945,7 @@ public: delayed_insert_threads--; mysql_mutex_unlock(&LOCK_thread_count); mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */ + DBUG_VOID_RETURN; } /* The following is for checking when we can delete ourselves */ @@ -3030,7 +3031,7 @@ bool Delayed_insert::handle_inserts(void thd.clear_error(); // reset error for binlog if (write_record(&thd, table, &info)) { - info.error_count++; // Ignore errors + info.stats.error_count++; // Ignore errors thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); row->log_query = 0; } @@ -3558,7 +3559,7 @@ bool select_insert::send_eof() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); - changed= (info.copied || info.deleted || info.updated); + changed= (info.stats.copied || info.stats.deleted || info.stats.updated); if (changed) { /* @@ -3605,21 +3606,21 @@ bool select_insert::send_eof() } char buff[160]; if (info.ignore) - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.records - info.copied), + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.stats.records, + (ulong) (info.stats.records - info.stats.copied), (ulong) thd->warning_info->statement_warn_count()); else - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.deleted+info.updated), + sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.stats.records, + (ulong) (info.stats.deleted+info.stats.updated), (ulong) thd->warning_info->statement_warn_count()); - row_count= info.copied + info.deleted + + row_count= info.stats.copied + info.stats.deleted + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated); + info.stats.touched : info.stats.updated); id= (thd->first_successful_insert_id_in_cur_stmt > 0) ? thd->first_successful_insert_id_in_cur_stmt : (thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : - (info.copied ? autoinc_value_of_last_inserted_row : 0)); + (info.stats.copied ? autoinc_value_of_last_inserted_row : 0)); ::my_ok(thd, row_count, id, buff); DBUG_RETURN(0); } @@ -3657,7 +3658,7 @@ void select_insert::abort_result_set() { If table creation failed, the number of rows modified will also be zero, so no check for that is made. */ - changed= (info.copied || info.deleted || info.updated); + changed= (info.stats.copied || info.stats.deleted || info.stats.updated); transactional_table= table->file->has_transactions(); if (thd->transaction.stmt.modified_non_trans_table) { === modified file 'sql/sql_load.cc' --- a/sql/sql_load.cc 2011-05-10 14:18:34 +0000 +++ b/sql/sql_load.cc 2011-05-11 13:05:53 +0000 @@ -585,8 +585,8 @@ int mysql_load(THD *thd,sql_exchange *ex error= -1; // Error on read goto err; } - sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted, - (ulong) (info.records - info.copied), + sprintf(name, ER(ER_LOAD_INFO), (ulong) info.stats.records, (ulong) info.stats.deleted, + (ulong) (info.stats.records - info.stats.copied), (ulong) thd->warning_info->statement_warn_count()); if (thd->transaction.stmt.modified_non_trans_table) @@ -636,9 +636,9 @@ int mysql_load(THD *thd,sql_exchange *ex #endif /*!EMBEDDED_LIBRARY*/ /* ok to client sent only after binlog write and engine commit */ - my_ok(thd, info.copied + info.deleted, 0L, name); + my_ok(thd, info.stats.copied + info.stats.deleted, 0L, name); err: - DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) || + DBUG_ASSERT(transactional_table || !(info.stats.copied || info.stats.deleted) || thd->transaction.stmt.modified_non_trans_table); table->file->ha_release_auto_increment(); table->auto_increment_field_not_null= FALSE; === modified file 'sql/table.cc' --- a/sql/table.cc 2011-05-10 14:18:34 +0000 +++ b/sql/table.cc 2011-05-11 13:05:53 +0000 @@ -5570,13 +5570,6 @@ bool TABLE::set_function_defaults(COPY_I const MY_BITMAP *used_defaults= operation.get_function_default_columns(*this); - DBUG_PRINT("wl5874_important", ("current_thd := %p mem_root %p in_use %p this %p", - current_thd, - current_thd->mem_root, - in_use, - this - )); - if (used_defaults == NULL) { DBUG_PRINT("wl5874", ("error")); === modified file 'unittest/gunit/copy_info-t.cc' --- a/unittest/gunit/copy_info-t.cc 2011-05-10 14:18:34 +0000 +++ b/unittest/gunit/copy_info-t.cc 2011-05-11 13:05:53 +0000 @@ -37,14 +37,51 @@ TABLE *make_table(Field **columns, int n return table; } +TEST_F(ServerTest, constructors) +{ + TABLE_LIST *table_list= NULL; + COPY_INFO insert_cum_update(COPY_INFO::INSERT_OPERATION, + table_list, + reinterpret_cast*>(1), + reinterpret_cast*>(2), + reinterpret_cast*>(3), + DUP_UPDATE, + true); + + EXPECT_EQ(0U, insert_cum_update.stats.records); + EXPECT_EQ(0U, insert_cum_update.stats.deleted); + EXPECT_EQ(0U, insert_cum_update.stats.updated); + EXPECT_EQ(0U, insert_cum_update.stats.copied); + EXPECT_EQ(0U, insert_cum_update.stats.error_count); + EXPECT_EQ(0U, insert_cum_update.stats.touched); + + insert_cum_update.stats.records= 1; + insert_cum_update.stats.deleted= 2; + insert_cum_update.stats.updated= 3; + insert_cum_update.stats.copied= 4; + insert_cum_update.stats.error_count= 5; + insert_cum_update.stats.touched= 6; + + COPY_INFO on_duplicate_update(COPY_INFO::UPDATE_OPERATION, + insert_cum_update); + + EXPECT_EQ(1U, on_duplicate_update.stats.records); + EXPECT_EQ(2U, on_duplicate_update.stats.deleted); + EXPECT_EQ(3U, on_duplicate_update.stats.updated); + EXPECT_EQ(4U, on_duplicate_update.stats.copied); + EXPECT_EQ(5U, on_duplicate_update.stats.error_count); + EXPECT_EQ(6U, on_duplicate_update.stats.touched); + +} + TEST_F(ServerTest, determine_default_assigned_columns_NULL) { Field_string a(NULL, 0, NULL, 0, Field::NONE, "a", &my_charset_latin1); Field_string b(NULL, 0, NULL, 0, Field::NONE, "b", &my_charset_latin1); Field *fields[2] = { &a, &b }; TABLE *table= make_table(fields, 2); - COPY_INFO dml_op(COPY_INFO::INSERT_OPERATION, NULL, NULL, NULL, NULL, DUP_ERROR, - false); + List > all_rows; + COPY_INFO dml_op(COPY_INFO::INSERT_OPERATION, NULL, &all_rows); MY_BITMAP *cols= get_default_assigned_columns(*table, NULL, dml_op); EXPECT_TRUE(bitmap_is_clear_all(cols)); @@ -68,7 +105,7 @@ TEST_F(ServerTest, determine_default_ass List insert_fields; insert_fields.push_front(new Item_field(&a)); - COPY_INFO dml_op(COPY_INFO::INSERT_OPERATION, NULL, NULL, NULL, NULL, DUP_ERROR, + COPY_INFO dml_op(COPY_INFO::INSERT_OPERATION, NULL, NULL, NULL, NULL, DUP_UPDATE, false); // This must be handled --===============1887546334== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/martin.hansson@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: martin.hansson@stripped\ # a5ocq72eg25l0t6e # target_branch: file:///data0/martin/bzrroot/bug11746628/t-work/ # testament_sha1: c5e1219f2b4940949eac956069693a8995cd075b # timestamp: 2011-05-11 15:07:02 +0200 # base_revision_id: martin.hansson@stripped\ # xclef2kldusqz5if # # Begin bundle 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 X0W2l5m7p5Y6PzQQIl8py3v1F3JFOFCQsiDCxQ== --===============1887546334==--