diff options
61 files changed, 5375 insertions, 540 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h index 0988d20f97f..80ce1b4b014 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -128,6 +128,8 @@ enum enum_server_command reserved by MySQL Cluster */ #define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25, reserved by MySQL Cluster */ +#define HAS_EXPLICIT_DEFAULT (1 << 26) /* An INSERT/UPDATE operation supplied + an explicit default value */ #define REFRESH_GRANT 1 /* Refresh grant tables */ #define REFRESH_LOG 2 /* Start on new log file */ diff --git a/mysql-test/include/function_defaults.inc b/mysql-test/include/function_defaults.inc new file mode 100644 index 00000000000..e588c82df1b --- /dev/null +++ b/mysql-test/include/function_defaults.inc @@ -0,0 +1,1166 @@ +SET TIME_ZONE = "+00:00"; + +--echo # +--echo # Test of errors for column data types that dont support function +--echo # defaults. +--echo # +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a BIT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a TINYINT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a SMALLINT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a MEDIUMINT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a INT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a BIGINT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a FLOAT DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a DECIMAL DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a DATE DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a TIME DEFAULT $current_timestamp ); +--error ER_INVALID_DEFAULT +eval CREATE TABLE t1( a YEAR DEFAULT $current_timestamp ); + +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a BIT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a TINYINT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a SMALLINT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a MEDIUMINT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a INT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a BIGINT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a FLOAT ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a DECIMAL ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a DATE ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a TIME ON UPDATE $current_timestamp ); +--error ER_INVALID_ON_UPDATE +eval CREATE TABLE t1( a YEAR ON UPDATE $current_timestamp ); + +--echo # +--echo # Test that the default clause behaves like NOW() regarding time zones. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT $current_timestamp, + c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + d $timestamp NULL, + e $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + f $datetime DEFAULT $current_timestamp, + g $datetime ON UPDATE $current_timestamp, + h $datetime +); + +--echo # 2011-09-27 14:11:08 UTC +SET TIMESTAMP = 1317132668.654321; +SET @old_time_zone = @@TIME_ZONE; +SET TIME_ZONE = "+05:00"; + +eval INSERT INTO t1( d, h ) VALUES ( $now, $now ); +SELECT * FROM t1; + +--echo # 1989-05-13 01:02:03 +SET TIMESTAMP = 611017323.543212; +eval UPDATE t1 SET d = $now, h = $now; +SELECT * FROM t1; + +SET TIME_ZONE = @old_time_zone; +DROP TABLE t1; + +--echo # +--echo # Test of several TIMESTAMP columns with different function defaults. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $timestamp NOT NULL DEFAULT $current_timestamp, + d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + e $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + f INT +); + +--echo # 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; + +INSERT INTO t1 ( f ) VALUES (1); +SELECT * FROM t1; + +--echo # 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798.132435; + +UPDATE t1 SET f = 2; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of inserted values out of order. +--echo # +eval CREATE TABLE t1 ( + a INT, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $timestamp NOT NULL DEFAULT $current_timestamp, + d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + e $timestamp NULL, + f $datetime, + g $datetime DEFAULT $current_timestamp, + h $datetime ON UPDATE $current_timestamp, + i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + j INT +); + +--echo # 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; + +INSERT INTO t1 ( j, a ) VALUES ( 1, 1 ); +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of ON DUPLICATE KEY UPDATE +--echo # +eval CREATE TABLE t1 ( + a INT PRIMARY KEY, + b INT, + c $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + d $timestamp NOT NULL DEFAULT $current_timestamp, + e $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + f $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765', + g $timestamp NULL, + h $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + i $datetime DEFAULT $current_timestamp, + j $datetime ON UPDATE $current_timestamp, + k $datetime NULL, + l $datetime DEFAULT '1986-09-27 03:00:00.098765' +); + +--echo # 1977-12-21 23:00:00 UTC +SET TIMESTAMP = 251593200.192837; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; + +--echo # 1975-05-21 23:00:00 UTC +SET TIMESTAMP = 169945200.918273; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; + +--echo # 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; + +DROP TABLE t1; + +eval CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp ); + +--echo # 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798.945156; + +INSERT INTO t1 VALUES + (1, 0, '2001-01-01 01:01:01.111111'), + (2, 0, '2002-02-02 02:02:02.222222'), + (3, 0, '2003-03-03 03:03:03.333333'); +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.444444' 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.444444'), + (6, '2006-06-06 06:06:06.666666') +ON DUPLICATE KEY UPDATE b = 4; + +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo # +--echo # Test of REPLACE INTO executed as UPDATE. +--echo # +eval CREATE TABLE t1 ( + a INT PRIMARY KEY, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + d $timestamp NOT NULL DEFAULT $current_timestamp, + e $datetime DEFAULT $current_timestamp, + f $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + g $datetime ON UPDATE $current_timestamp, + h $timestamp NULL, + i $datetime +); + +--echo # 1970-09-21 09:11:12 UTC +SET TIMESTAMP = 22756272.163584; + +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; + +--echo # 1970-11-10 14:16:17 UTC +SET TIMESTAMP = 27094577.852954; + + +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo # +--echo # Test of insertion of NULL, DEFAULT and an empty row for DEFAULT +--echo # CURRENT_TIMESTAMP. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $datetime DEFAULT $current_timestamp, + c INT +); + +--echo # 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.163578; + +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"; + +DROP TABLE t1; + +--echo # 2011-04-20 07:05:39 UTC +SET TIMESTAMP = 1303283139.195624; +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE $current_timestamp, + 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; + +--echo # 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.136952; + +eval CREATE TABLE t1 ( +a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, +b $timestamp NOT NULL DEFAULT $current_timestamp, +c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, +d $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +e $timestamp NULL, +f $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, +g $datetime DEFAULT $current_timestamp, +h $datetime ON UPDATE $current_timestamp, +i $datetime NULL, +j $datetime DEFAULT '1986-09-27 03:00:00.098765' +); + +INSERT INTO t1 VALUES (); + +INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL; + +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $datetime DEFAULT $current_timestamp, + c INT +); + +INSERT INTO t1 ( c ) VALUES (1); +SELECT * FROM t1; + +--echo # 2011-04-20 17:06:13 UTC +SET TIMESTAMP = 1303311973.163587; + +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; + +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp, + b $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + c $datetime DEFAULT $current_timestamp, + d $datetime ON UPDATE $current_timestamp, + e INT +); + +eval CREATE TABLE t2 ( + f INT, + g $datetime ON UPDATE $current_timestamp, + h $datetime DEFAULT $current_timestamp, + i $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + j $timestamp NOT NULL DEFAULT $current_timestamp +); + +--echo # 1995-03-11 00:02:03 UTC +SET TIMESTAMP = 794880123.195676; + +INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 ); + +INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 ); + +SELECT * FROM t1; +SELECT * FROM t2; + +--echo # 1980-12-13 02:02:01 UTC +SET TIMESTAMP = 345520921.196755; + +UPDATE t1, t2 SET t1.e = 3, t2.f = 4; + +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1, t2; + +--echo # +--echo # Test of multiple table update with temporary table and on the fly. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + b $datetime ON UPDATE $current_timestamp, + c INT, + d INT +); + +eval CREATE TABLE t2 ( + a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + b $datetime ON UPDATE $current_timestamp, + c INT KEY, + d INT +); + +INSERT INTO t1 ( c ) VALUES (1), (2); +INSERT INTO t2 ( c ) VALUES (1), (2); + +--echo # Test of multiple table update done on the fly +--echo # 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.194685; +UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1; +SELECT * FROM t1; +SELECT * FROM t2; + +--echo # Test of multiple table update done with temporary table. +--echo # 1979-01-15 03:02:01 +SET TIMESTAMP = 285213721.134679; +UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1; +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1, t2; + + +--echo # +--echo # Test of ON UPDATE CURRENT_TIMESTAMP. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + b $datetime ON UPDATE $current_timestamp, + c INT +); + +--echo # 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.794613; + +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 # +--echo # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP +--echo # +--echo # 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.534231; + +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 a multiple-table update where only one table is updated and +--echo # the updated table has a primary key. +--echo # +eval CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) ); +INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4); + +eval CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5); + +UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a; + +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1, t2; + +--echo # +--echo # Test of ALTER TABLE, reordering columns. +--echo # +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b INT );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, c $timestamp NULL );eval ALTER TABLE t1 MODIFY b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a INT, b $timestamp NULL );eval ALTER TABLE t1 MODIFY b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b $timestamp NULL );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, b $timestamp NULL );eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now, b INT, c $timestamp NULL ); +SHOW CREATE TABLE t1;eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now, b INT, c $timestamp NULL );eval ALTER TABLE t1 MODIFY c $timestamp NULL FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b INT, c $timestamp NULL ); +SHOW CREATE TABLE t1;eval ALTER TABLE t1 MODIFY a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp AFTER b; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b INT, c $timestamp NULL );eval ALTER TABLE t1 MODIFY c $timestamp NULL FIRST; +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +--echo # +--echo # Test of ALTER TABLE, adding columns. +--echo # +eval CREATE TABLE t1 ( a INT ); +eval ALTER TABLE t1 ADD COLUMN b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # Test of INSERT SELECT. +--echo # +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + d $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp +); + +eval CREATE TABLE t2 ( + placeholder1 INT, + placeholder2 INT, + placeholder3 INT, + placeholder4 INT, + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + c $datetime, + d $datetime +); + +--echo # 1977-08-16 15:30:01 UTC +SET TIMESTAMP = 240589801.654312; + +INSERT INTO t2 (a, b, c, d) VALUES ( + '1977-08-16 15:30:01.123456', + '1977-08-16 15:30:01.234567', + '1977-08-16 15:30:01.345678', + '1977-08-16 15:30:01.456789' +); + +--echo # 1986-09-27 01:00:00 UTC +SET TIMESTAMP = 528166800.132435; + +INSERT INTO t1 ( a, c ) SELECT a, c FROM t2; + +SELECT * FROM t1; + +DROP TABLE t1, t2; + +--echo # +--echo # Test of CREATE TABLE SELECT. +--echo # +--echo # We test that the columns of the source table are not used to determine +--echo # function defaults for the receiving table. +--echo # + +--echo # 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.657898; +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT $current_timestamp, + c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + d $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765', + e $timestamp NULL, + f $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + g $datetime DEFAULT $current_timestamp, + h $datetime ON UPDATE $current_timestamp, + i $datetime NULL, + j $datetime DEFAULT '1986-09-27 03:00:00.098765' +); + +INSERT INTO t1 VALUES (); + +--echo # 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.164937; + +eval CREATE TABLE t2 SELECT a FROM t1; SHOW CREATE TABLE t2; SELECT * FROM t2; +eval CREATE TABLE t3 SELECT b FROM t1; SHOW CREATE TABLE t3; SELECT * FROM t3; +eval CREATE TABLE t4 SELECT c FROM t1; SHOW CREATE TABLE t4; SELECT * FROM t4; +eval CREATE TABLE t5 SELECT d FROM t1; SHOW CREATE TABLE t5; SELECT * FROM t5; +eval CREATE TABLE t6 SELECT e FROM t1; SHOW CREATE TABLE t6; SELECT * FROM t6; +eval CREATE TABLE t7 SELECT f FROM t1; SHOW CREATE TABLE t7; SELECT * FROM t7; +eval CREATE TABLE t8 SELECT g FROM t1; SHOW CREATE TABLE t8; SELECT * FROM t8; +eval CREATE TABLE t9 SELECT h FROM t1; SHOW CREATE TABLE t9; SELECT * FROM t9; +eval CREATE TABLE t10 SELECT i FROM t1; SHOW CREATE TABLE t10; SELECT * FROM t10; +eval CREATE TABLE t11 SELECT j FROM t1; SHOW CREATE TABLE t11; SELECT * FROM t11; + +eval CREATE TABLE t12 ( + k $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + l $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + m $timestamp NOT NULL DEFAULT $current_timestamp, + n $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + o $timestamp NOT NULL DEFAULT '1986-09-27 03:00:00.098765', + p $timestamp NULL, + q $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + r $datetime DEFAULT $current_timestamp, + s $datetime ON UPDATE $current_timestamp, + t $datetime NULL, + u $datetime DEFAULT '1986-09-27 03:00:00.098765' +) +SELECT * FROM t1; + +SHOW CREATE TABLE t12; + +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12; + +--echo # 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.164953; +eval CREATE TABLE t1 ( + a $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $datetime DEFAULT $current_timestamp, + c $datetime ON UPDATE $current_timestamp, + d $datetime NULL, + e $datetime DEFAULT '1986-09-27 03:00:00.098765' +); + +INSERT INTO t1 VALUES (); + +--echo # 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.915736; + +eval CREATE TABLE t2 SELECT a FROM t1; +SHOW CREATE TABLE t2; +SELECT * FROM t2; + +eval CREATE TABLE t3 SELECT b FROM t1; +SHOW CREATE TABLE t3; +SELECT * FROM t3; + +eval CREATE TABLE t4 SELECT c FROM t1; +SHOW CREATE TABLE t4; +SELECT * FROM t4; + +eval CREATE TABLE t5 SELECT d FROM t1; +SHOW CREATE TABLE t5; +SELECT * FROM t5; + +eval CREATE TABLE t6 SELECT e FROM t1; +SHOW CREATE TABLE t6; +SELECT * FROM t6; + +DROP TABLE t1, t2, t3, t4, t5, t6; + +--echo # +--echo # Test of a CREATE TABLE SELECT that also declared columns. In this case +--echo # the function default should be de-activated during the execution of the +--echo # CREATE TABLE statement. +--echo # +--echo # 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.987654; +eval CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES ( 1 ), ( 2 ); + +eval CREATE TABLE t2 ( b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp) SELECT a FROM t1; + +SHOW CREATE TABLE t2; +SET TIMESTAMP = 2000.876543; +INSERT INTO t2( a ) VALUES ( 3 ); +SELECT * FROM t2; + +DROP TABLE t1, t2; + +--echo # +--echo # Test of updating a view. +--echo # +eval CREATE TABLE t1 ( a INT, b $datetime DEFAULT $current_timestamp ); +eval CREATE TABLE t2 ( a INT, b $datetime ON UPDATE $current_timestamp ); + +eval CREATE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; + +eval CREATE VIEW v2 AS SELECT * FROM t2; +SHOW CREATE VIEW v2; + +--echo # 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.348564; + +INSERT INTO v1 ( a ) VALUES ( 1 ); +INSERT INTO v2 ( a ) VALUES ( 1 ); + +SELECT * FROM t1; +SELECT * FROM v1; + +SELECT * FROM t2; +SELECT * FROM v2; + +--echo # 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.567332; +UPDATE v1 SET a = 2; +UPDATE v2 SET a = 2; + +SELECT * FROM t1; +SELECT * FROM v1; + +SELECT * FROM t2; +SELECT * FROM v2; + +DROP VIEW v1, v2; +DROP TABLE t1, t2; + +--echo # +--echo # Test with stored procedures. +--echo # +eval CREATE TABLE t1 ( + a INT, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $timestamp NOT NULL DEFAULT $current_timestamp, + d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + e $timestamp NULL, + f $datetime DEFAULT $current_timestamp, + g $datetime ON UPDATE $current_timestamp +); +CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 ); +CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1; + +--echo # 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.876544; +CALL p1(); +SELECT * FROM t1; + +--echo # 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.143546; +CALL p2(); +SELECT * FROM t1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; + +--echo # +--echo # Test with triggers. +--echo # +eval CREATE TABLE t1 ( + a INT, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $timestamp NOT NULL DEFAULT $current_timestamp, + d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + e $timestamp NULL, + f $datetime, + g $datetime DEFAULT $current_timestamp, + h $datetime ON UPDATE $current_timestamp, + i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp +); + +eval CREATE TABLE t2 ( a INT ); + +DELIMITER |; +eval CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN + INSERT INTO t1 ( a ) VALUES ( 1 ); +END| +DELIMITER ;| + +--echo # 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.978675; + +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; + +DROP TRIGGER t2_trg; + +DELIMITER |; +eval CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN + UPDATE t1 SET a = 2; +END| +DELIMITER ;| + +--echo # 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.456789; + +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; + +DROP TABLE t1, t2; + +--echo # +--echo # Test where the assignment target is not a column. +--echo # +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp ); +eval CREATE TABLE t2 ( a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp ); +eval CREATE TABLE t3 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp ); +eval CREATE TABLE t4 ( a $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp ); + +eval CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1; +eval CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2; +eval CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3; +eval CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4; + +INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t1; + +INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t2; + +INSERT INTO t3 VALUES (); +UPDATE v3 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t3; + +INSERT INTO t4 VALUES (); +UPDATE v4 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t4; + +DROP VIEW v1, v2, v3, v4; +DROP TABLE t1, t2, t3, t4; + +--echo # +--echo # Test of LOAD DATA/XML INFILE +--echo # This tests behavior of function defaults for TIMESTAMP and DATETIME +--echo # columns. during LOAD ... INFILE. +--echo # As can be seen here, a TIMESTAMP column with only ON UPDATE +--echo # CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD +--echo # ... INFILE if the value is missing. For DATETIME columns a NULL value +--echo # is inserted instead. +--echo # + +eval CREATE TABLE t1 ( + a INT, + b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + c $timestamp NOT NULL DEFAULT $current_timestamp, + d $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + e $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + f $datetime, + g $datetime DEFAULT $current_timestamp, + h $datetime ON UPDATE $current_timestamp, + i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp +); + +eval CREATE TABLE t2 ( + a $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + b $timestamp NOT NULL DEFAULT $current_timestamp, + c $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $current_timestamp, + d $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + e $datetime NOT NULL, + f $datetime NOT NULL DEFAULT '1977-01-02 12:13:14', + g $datetime DEFAULT $current_timestamp NOT NULL, + h $datetime ON UPDATE $current_timestamp NOT NULL, + i $datetime DEFAULT $current_timestamp ON UPDATE $current_timestamp NOT NULL +); + +SELECT 1 INTO OUTFILE 't3.dat' FROM dual; + +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +INTO OUTFILE 't4.dat' +FROM dual; + +SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual; + +--echo # Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.918273; + +LOAD DATA INFILE 't3.dat' INTO TABLE t1; +--query_vertical SELECT * FROM t1 + +LOAD DATA INFILE 't4.dat' INTO TABLE t2; +SELECT a FROM t2; +SELECT b FROM t2; +SELECT c FROM t2; +SELECT d FROM t2; +--echo # As shown here, supplying a NULL value to a non-nullable +--echo # column with no default value results in the zero date. +SELECT e FROM t2; +--echo # As shown here, supplying a NULL value to a non-nullable column with a +--echo # default value results in the zero date. +SELECT f FROM t2; +--echo # As shown here, supplying a NULL value to a non-nullable column with a +--echo # default function results in the zero date. +SELECT g FROM t2; +--echo # As shown here, supplying a NULL value to a non-nullable DATETIME ON +--echo # UPDATE CURRENT_TIMESTAMP column with no default value results in the +--echo # zero date. +SELECT h FROM t2; +SELECT i FROM t2; + +DELETE FROM t1; +DELETE FROM t2; + +--echo # Read t3 file into t1 +--echo # The syntax will cause a different code path to be taken +--echo # (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command +--echo # above. The code in this path is copy-pasted code from the path taken +--echo # under the syntax used in the previous LOAD command. +LOAD DATA INFILE 't3.dat' INTO TABLE t1 +FIELDS TERMINATED BY '' ENCLOSED BY ''; + +SELECT b FROM t1; +SELECT c FROM t1; +SELECT d FROM t1; +SELECT e FROM t1; +--echo # Yes, a missing field cannot be NULL using this syntax, so it will +--echo # zero date instead. Says a comment in read_fixed_length() : "No fields +--echo # specified in fields_vars list can be NULL in this format." +--echo # It appears to be by design. This is inconsistent with LOAD DATA INFILE +--echo # syntax in previous test. +SELECT f FROM t1; +SELECT g FROM t1; +--echo # See comment above "SELECT f FROM f1". +SELECT h FROM t1; +SELECT i FROM t1; +DELETE FROM t1; + +LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy ); +SELECT * FROM t1; +SELECT @dummy; +DELETE FROM t1; + +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10'; +SELECT * FROM t1; +DELETE FROM t1; + +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10'; +SELECT * FROM t1; +DELETE FROM t1; + +--echo # Load a static XML file +LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1 +ROWS IDENTIFIED BY '<row>'; + +--echo Missing tags are treated as NULL +--query_vertical SELECT * FROM t1 + +DROP TABLE t1, t2; + +let $MYSQLD_DATADIR= `select @@datadir`; +remove_file $MYSQLD_DATADIR/test/t3.dat; +remove_file $MYSQLD_DATADIR/test/t4.dat; +remove_file $MYSQLD_DATADIR/test/t5.dat; + + +--echo # +--echo # Similar LOAD DATA tests in another form +--echo # +--echo # All of this test portion has been run on a pre-WL5874 trunk +--echo # (except that like_b and like_c didn't exist) and all result +--echo # differences are a bug. +--echo # Regarding like_b its definition is the same as b's except +--echo # that the constant default is replaced with a function +--echo # default. Our expectation is that like_b would behave +--echo # like b: if b is set to NULL, or set to 0000-00-00, or set to +--echo # its default, then the same should apply to like_b. Same for +--echo # like_c vs c. + +--echo # Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.089786; + +SELECT 1 INTO OUTFILE "file1.dat" FROM dual; +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + INTO OUTFILE "file2.dat" FROM dual; + +--echo # Too short row + +eval +CREATE TABLE t1 ( + dummy INT, + a $datetime NULL DEFAULT NULL, + b $datetime NULL DEFAULT "2011-11-18", + like_b $datetime NULL DEFAULT $current_timestamp, + c $datetime NOT NULL DEFAULT "2011-11-18", + like_c $datetime NOT NULL DEFAULT $current_timestamp, + d $timestamp NULL DEFAULT "2011-05-03" ON UPDATE $current_timestamp, + e $timestamp NOT NULL DEFAULT "2011-05-03", + f $timestamp NOT NULL DEFAULT $current_timestamp, + g $timestamp NULL DEFAULT NULL, + h INT NULL, + i INT NOT NULL DEFAULT 42 +); + +--echo # There is no promotion +SHOW CREATE TABLE t1; + +LOAD DATA INFILE "file1.dat" INTO table t1; + +--echo # It is strange that "like_b" gets NULL when "b" gets 0. But +--echo # this is consistent with how "a" gets NULL when "b" gets 0, +--echo # with how "g" gets NULL when "d" gets 0, and with how "h" gets +--echo # NULL when "i" gets 0. Looks like "DEFAULT +--echo # <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL +--echo # and DEFAULT NOW are changed to NULL. +--query_vertical SELECT * FROM t1 +delete from t1; + +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; + +--echo # There is no promotion +SHOW CREATE TABLE t1; + +LOAD DATA INFILE "file1.dat" INTO table t1; + +--query_vertical SELECT * FROM t1 +delete from t1; + +drop table t1; + +--echo # Conclusion derived from trunk's results: +--echo # DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00, +--echo # DATETIME DEFAULT NULL (a) gets NULL, +--echo # TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00, +--echo # TIMESTAMP NULL DEFAULT NULL (g) gets NULL, +--echo # TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL, +--echo # TIMESTAMP NOT NULL (f before ALTER, e) gets NOW. + +--echo ### Loading NULL ### + +eval +CREATE TABLE t1 ( + dummy INT, + a $datetime NULL DEFAULT NULL, + b $datetime NULL DEFAULT "2011-11-18", + like_b $datetime NULL DEFAULT $current_timestamp, + c $datetime NOT NULL DEFAULT "2011-11-18", + like_c $datetime NOT NULL DEFAULT $current_timestamp, + d $timestamp NULL DEFAULT "2011-05-03" ON UPDATE $current_timestamp, + e $timestamp NOT NULL DEFAULT "2011-05-03", + f $timestamp NOT NULL DEFAULT $current_timestamp, + g $timestamp NULL DEFAULT NULL, + h INT NULL, + i INT NOT NULL DEFAULT 42 +); + +--echo # There is no promotion +SHOW CREATE TABLE t1; + +LOAD DATA INFILE "file2.dat" INTO table t1; + +--query_vertical SELECT * FROM t1 +delete from t1; + +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; + +--echo # There is no promotion +SHOW CREATE TABLE t1; + +LOAD DATA INFILE "file2.dat" INTO table t1; + +--query_vertical SELECT * FROM t1 +delete from t1; + +--echo # Conclusion derived from trunk's results: +--echo # DATETIME NULL (a,b) gets NULL, +--echo # DATETIME NOT NULL (c) gets 0000-00-00, +--echo # TIMESTAMP NULL (d,f,g) gets NULL, +--echo # TIMESTAMP NOT NULL (e) gets NOW. + +drop table t1; +remove_file $MYSQLD_DATADIR/test/file1.dat; +remove_file $MYSQLD_DATADIR/test/file2.dat; + +--echo # +--echo # Test of updatable views with check options. The option can be violated +--echo # using ON UPDATE updates which is very strange as this offers a loophole +--echo # in this integrity check. +--echo # +SET TIME_ZONE = "+03:00"; +--echo # 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.123456; + +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp) ENGINE = INNODB; + +SHOW CREATE TABLE t1; + +INSERT INTO t1 ( a ) VALUES ( 1 ); + +SELECT * FROM t1; + +eval CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456' +WITH CHECK OPTION; + +SELECT * FROM v1; + +--echo # 1970-01-01 03:33:20 +SET TIMESTAMP = 2000.000234; + +--error ER_VIEW_CHECK_FAILED +UPDATE v1 SET a = 2; +SELECT * FROM t1; + +DROP VIEW v1; +DROP TABLE t1; + +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE $current_timestamp, + c INT KEY +); +--echo # 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1 ( c ) VALUES ( 1 ); + +eval CREATE VIEW v1 AS +SELECT * +FROM t1 +WHERE a >= '1973-08-14 09:11:22' +WITH LOCAL CHECK OPTION; + +SELECT * FROM v1; + +SET TIMESTAMP = 1.126789; + +--error ER_VIEW_CHECK_FAILED +INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2; + +SELECT * FROM v1; + +DROP VIEW v1; +DROP TABLE t1; + +--echo # +--echo # Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE +--echo # +eval CREATE TABLE t1 ( + a INT, + b INT, + ts $timestamp NOT NULL DEFAULT $current_timestamp ON UPDATE $current_timestamp, + PRIMARY KEY ( a, ts ) +) ENGINE = INNODB; +INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' ); + +eval CREATE TABLE t2 ( a INT ) ENGINE = INNODB; +INSERT INTO t2 VALUES ( 1 ); + +UPDATE t1 STRAIGHT_JOIN t2 +SET t1.b = t1.b + 1 +WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00'; + +SELECT b FROM t1; + +DROP TABLE t1, t2; + +--echo # +--echo # Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT +--echo # CURRENT_TIMESTAMP INSERTS ZERO +--echo # +SET timestamp = 1000; + +CREATE TABLE t1 ( b INT ); +INSERT INTO t1 VALUES (1); + +eval ALTER TABLE t1 ADD COLUMN a6 $datetime DEFAULT $now ON UPDATE $now FIRST; +eval ALTER TABLE t1 ADD COLUMN a5 $datetime DEFAULT $now FIRST; +eval ALTER TABLE t1 ADD COLUMN a4 $datetime ON UPDATE $now FIRST; + +eval ALTER TABLE t1 ADD COLUMN a3 $timestamp NOT NULL DEFAULT $now ON UPDATE $now FIRST; +eval ALTER TABLE t1 ADD COLUMN a2 $timestamp NOT NULL DEFAULT $now FIRST; +eval ALTER TABLE t1 ADD COLUMN a1 $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now FIRST; + +eval ALTER TABLE t1 ADD COLUMN c1 $timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE $now AFTER b; +eval ALTER TABLE t1 ADD COLUMN c2 $timestamp NOT NULL DEFAULT $now AFTER c1; +eval ALTER TABLE t1 ADD COLUMN c3 $timestamp NOT NULL DEFAULT $now ON UPDATE $now AFTER c2; + +eval ALTER TABLE t1 ADD COLUMN c4 $datetime ON UPDATE $now AFTER c3; +eval ALTER TABLE t1 ADD COLUMN c5 $datetime DEFAULT $now AFTER c4; +eval ALTER TABLE t1 ADD COLUMN c6 $datetime DEFAULT $now ON UPDATE $now AFTER c5; + +SELECT * FROM t1; + +DROP TABLE t1; + + +eval CREATE TABLE t1 ( a $timestamp NOT NULL DEFAULT $now ON UPDATE $current_timestamp, b $datetime DEFAULT $now ); +INSERT INTO t1 VALUES (); + +SET timestamp = 1000000000; + +ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3); +ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3); + +SELECT * FROM t1; + +DROP TABLE t1; + + +eval CREATE TABLE t1 ( + a $timestamp NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE $current_timestamp, + b $datetime DEFAULT '1999-12-01 11:22:33' +); +INSERT INTO t1 VALUES (); + +eval ALTER TABLE t1 MODIFY COLUMN a $timestamp DEFAULT $now; +eval ALTER TABLE t1 MODIFY COLUMN b $datetime DEFAULT $now; +INSERT INTO t1 VALUES (); + +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/include/function_defaults_notembedded.inc b/mysql-test/include/function_defaults_notembedded.inc new file mode 100644 index 00000000000..d9708c13da5 --- /dev/null +++ b/mysql-test/include/function_defaults_notembedded.inc @@ -0,0 +1,94 @@ +SET TIME_ZONE = "+00:00"; + +--echo # +--echo # Test of INSERT DELAYED ... SET ... +--echo # + +--echo # 2011-04-19 08:02:40 UTC +SET TIMESTAMP = 1303200160.123456; + +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp); + +INSERT DELAYED INTO t1 SET a = 1; +FLUSH TABLE t1; + +SELECT * FROM t1; +SELECT * FROM t1 WHERE b = 0; + +INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060'; +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.234567; + +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$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.789123'); +FLUSH TABLE t1; +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Test of a delayed insert handler servicing two insert operations +--echo # with different sets of active defaults. +--echo # +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp); + +--connect(con1, localhost, root,,) +--echo # 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241.345678; +SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go'; +--send INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3) + +--connection default +SET debug_sync = 'now WAIT_FOR parked'; + +--connect(con2, localhost, root,,) +--echo # 2011-04-19 08:04:01 UTC +SET TIME_ZONE="+03:00"; +SET TIMESTAMP = 1303200241.456789; +--send INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345') + +--connection default +SET debug_sync = 'now SIGNAL go'; + +--let $wait_condition= SELECT COUNT(*) = 6 FROM t1 +--source include/wait_condition.inc + +--sorted_result +SELECT * FROM t1; + +--disconnect con1 +--disconnect con2 + +DROP TABLE t1; + +--echo # +--echo # Test of early activation of function defaults. +--echo # + +eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp); + +SET TIMESTAMP = 1317235172.987654; # 2011-09-28 18:39:32 UTC +INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3); + +SET TIMESTAMP = 385503754.876543; # 1982-03-20 20:22:34 UTC +INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6); + +FLUSH TABLE t1; +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index ba52959be84..7102968a8d7 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -55,9 +55,9 @@ ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int); ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long create table t1 (a datetime default now()); -ERROR 42000: Invalid default value for 'a' +drop table t1; create table t1 (a datetime on update now()); -ERROR HY000: Invalid ON UPDATE clause for 'a' column +drop table t1; create table t1 (a int default 100 auto_increment); ERROR 42000: Invalid default value for 'a' create table t1 (a tinyint default 1000); diff --git a/mysql-test/r/function_defaults.result b/mysql-test/r/function_defaults.result new file mode 100644 index 00000000000..27b9ee0a323 --- /dev/null +++ b/mysql-test/r/function_defaults.result @@ -0,0 +1,3067 @@ +# +# Test of function defaults for any server, including embedded. +# +# +# Function defaults run 1. No microsecond precision. +# +SET TIME_ZONE = "+00:00"; +# +# Test of errors for column data types that dont support function +# defaults. +# +CREATE TABLE t1( a BIT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a TINYINT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a SMALLINT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a MEDIUMINT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a INT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a BIGINT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a FLOAT DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a DECIMAL DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a DATE DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a TIME DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a YEAR DEFAULT CURRENT_TIMESTAMP ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a BIT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a TINYINT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a SMALLINT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a MEDIUMINT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a INT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a BIGINT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a FLOAT ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a DECIMAL ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a DATE ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a TIME ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a YEAR ON UPDATE CURRENT_TIMESTAMP ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +# +# Test that the default clause behaves like NOW() regarding time zones. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NULL, +e DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +f DATETIME DEFAULT CURRENT_TIMESTAMP, +g DATETIME ON UPDATE CURRENT_TIMESTAMP, +h DATETIME +); +# 2011-09-27 14:11:08 UTC +SET TIMESTAMP = 1317132668.654321; +SET @old_time_zone = @@TIME_ZONE; +SET TIME_ZONE = "+05:00"; +INSERT INTO t1( d, h ) VALUES ( NOW(), NOW() ); +SELECT * FROM t1; +a b c d e f g h +2011-09-27 19:11:08 2011-09-27 19:11:08 0000-00-00 00:00:00 2011-09-27 19:11:08 2011-09-27 19:11:08 2011-09-27 19:11:08 NULL 2011-09-27 19:11:08 +# 1989-05-13 01:02:03 +SET TIMESTAMP = 611017323.543212; +UPDATE t1 SET d = NOW(), h = NOW(); +SELECT * FROM t1; +a b c d e f g h +1989-05-13 04:02:03 2011-09-27 19:11:08 1989-05-13 04:02:03 1989-05-13 04:02:03 1989-05-13 04:02:03 2011-09-27 19:11:08 1989-05-13 04:02:03 1989-05-13 04:02:03 +SET TIME_ZONE = @old_time_zone; +DROP TABLE t1; +# +# Test of several TIMESTAMP columns with different function defaults. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +f INT +); +# 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; +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.132435; +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 inserted values out of order. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NULL, +f DATETIME, +g DATETIME DEFAULT CURRENT_TIMESTAMP, +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +j INT +); +# 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; +INSERT INTO t1 ( j, a ) VALUES ( 1, 1 ); +SELECT * FROM t1; +a b c d e f g h i j +1 2011-04-19 07:22:02 2011-04-19 07:22:02 0000-00-00 00:00:00 NULL NULL 2011-04-19 07:22:02 NULL 2011-04-19 07:22:02 1 +DROP TABLE t1; +# +# Test of ON DUPLICATE KEY UPDATE +# +CREATE TABLE t1 ( +a INT PRIMARY KEY, +b INT, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +e TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +f TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +g TIMESTAMP NULL, +h DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +i DATETIME DEFAULT CURRENT_TIMESTAMP, +j DATETIME ON UPDATE CURRENT_TIMESTAMP, +k DATETIME NULL, +l DATETIME DEFAULT '1986-09-27 03:00:00.098765' +); +# 1977-12-21 23:00:00 UTC +SET TIMESTAMP = 251593200.192837; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 NULL 1977-12-21 23:00:00 1977-12-21 23:00:00 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 1977-12-21 23:00:00 1977-12-21 23:00:00 NULL NULL 1986-09-27 03:00:00 +# 1975-05-21 23:00:00 UTC +SET TIMESTAMP = 169945200.918273; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 2 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 1986-09-27 03:00:00 NULL 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 NULL 1986-09-27 03:00:00 +# 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 2 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 1986-09-27 03:00:00 NULL 1975-05-21 23:00:00 1977-12-21 23:00:00 1975-05-21 23:00:00 NULL 1986-09-27 03:00:00 +2 NULL 1973-08-14 09:11:22 1973-08-14 09:11:22 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 1973-08-14 09:11:22 1973-08-14 09:11:22 NULL NULL 1986-09-27 03:00:00 +DROP TABLE t1; +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); +# 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798.945156; +INSERT INTO t1 VALUES +(1, 0, '2001-01-01 01:01:01.111111'), +(2, 0, '2002-02-02 02:02:02.222222'), +(3, 0, '2003-03-03 03:03:03.333333'); +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.444444' 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.444444'), +(6, '2006-06-06 06:06:06.666666') +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 REPLACE INTO executed as UPDATE. +# +CREATE TABLE t1 ( +a INT PRIMARY KEY, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +e DATETIME DEFAULT CURRENT_TIMESTAMP, +f TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +g DATETIME ON UPDATE CURRENT_TIMESTAMP, +h TIMESTAMP NULL, +i DATETIME +); +# 1970-09-21 09:11:12 UTC +SET TIMESTAMP = 22756272.163584; +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1970-09-21 09:11:12 1970-09-21 09:11:12 1970-09-21 09:11:12 1970-09-21 09:11:12 0000-00-00 00:00:00 NULL NULL NULL +# 1970-11-10 14:16:17 UTC +SET TIMESTAMP = 27094577.852954; +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1970-11-10 14:16:17 1970-11-10 14:16:17 1970-11-10 14:16:17 1970-11-10 14:16:17 0000-00-00 00:00:00 NULL NULL NULL +DROP TABLE t1; +# +# Test of insertion of NULL, DEFAULT and an empty row for DEFAULT +# CURRENT_TIMESTAMP. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b DATETIME DEFAULT CURRENT_TIMESTAMP, +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.163578; +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"; +DROP TABLE t1; +# 2011-04-20 07:05:39 UTC +SET TIMESTAMP = 1303283139.195624; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE CURRENT_TIMESTAMP, +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; +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.136952; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +e TIMESTAMP NULL, +f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +g DATETIME DEFAULT CURRENT_TIMESTAMP, +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME NULL, +j DATETIME DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL; +SELECT * FROM t1; +a b c d e f g h i j +2011-04-20 09:53:41 2011-04-20 09:53:41 0000-00-00 00:00:00 1986-09-27 03:00:00 NULL 2011-04-20 09:53:41 2011-04-20 09:53:41 NULL NULL 1986-09-27 03:00:00 +2011-04-20 09:53:41 2011-04-20 09:53:41 2011-04-20 09:53:41 2011-04-20 09:53:41 NULL NULL NULL NULL NULL NULL +DROP TABLE t1; +# +# Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b DATETIME DEFAULT CURRENT_TIMESTAMP, +c INT +); +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 UTC +SET TIMESTAMP = 1303311973.163587; +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 15:06:13 2011-04-20 09:53:41 2 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +c DATETIME DEFAULT CURRENT_TIMESTAMP, +d DATETIME ON UPDATE CURRENT_TIMESTAMP, +e INT +); +CREATE TABLE t2 ( +f INT, +g DATETIME ON UPDATE CURRENT_TIMESTAMP, +h DATETIME DEFAULT CURRENT_TIMESTAMP, +i TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +j TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); +# 1995-03-11 00:02:03 UTC +SET TIMESTAMP = 794880123.195676; +INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 ); +INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 ); +SELECT * FROM t1; +a b c d e +1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 NULL 1 +1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 NULL 2 +SELECT * FROM t2; +f g h i j +1 NULL 1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 +2 NULL 1995-03-11 00:02:03 0000-00-00 00:00:00 1995-03-11 00:02:03 +# 1980-12-13 02:02:01 UTC +SET TIMESTAMP = 345520921.196755; +UPDATE t1, t2 SET t1.e = 3, t2.f = 4; +SELECT * FROM t1; +a b c d e +1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 3 +1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 3 +SELECT * FROM t2; +f g h i j +4 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 +4 1980-12-13 02:02:01 1995-03-11 00:02:03 1980-12-13 02:02:01 1995-03-11 00:02:03 +DROP TABLE t1, t2; +# +# Test of multiple table update with temporary table and on the fly. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +b DATETIME ON UPDATE CURRENT_TIMESTAMP, +c INT, +d INT +); +CREATE TABLE t2 ( +a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +b DATETIME ON UPDATE CURRENT_TIMESTAMP, +c INT KEY, +d INT +); +INSERT INTO t1 ( c ) VALUES (1), (2); +INSERT INTO t2 ( c ) VALUES (1), (2); +# Test of multiple table update done on the fly +# 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.194685; +UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1; +SELECT * FROM t1; +a b c d +0000-00-00 00:00:00 NULL 1 NULL +0000-00-00 00:00:00 NULL 2 NULL +SELECT * FROM t2; +a b c d +2011-04-20 15:06:13 2011-04-20 15:06:13 1 1 +2011-04-20 15:06:13 2011-04-20 15:06:13 2 1 +# Test of multiple table update done with temporary table. +# 1979-01-15 03:02:01 +SET TIMESTAMP = 285213721.134679; +UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1; +SELECT * FROM t1; +a b c d +1979-01-15 02:02:01 1979-01-15 02:02:01 1 1 +1979-01-15 02:02:01 1979-01-15 02:02:01 2 1 +SELECT * FROM t2; +a b c d +2011-04-20 15:06:13 2011-04-20 15:06:13 1 1 +2011-04-20 15:06:13 2011-04-20 15:06:13 2 1 +DROP TABLE t1, t2; +# +# Test of ON UPDATE CURRENT_TIMESTAMP. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +b DATETIME ON UPDATE CURRENT_TIMESTAMP, +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.794613; +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 +# +# Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP +# +# 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.534231; +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 a multiple-table update where only one table is updated and +# the updated table has a primary key. +# +CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) ); +INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4); +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5); +UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a; +SELECT * FROM t1; +a b +1 100 +2 100 +3 100 +4 100 +SELECT * FROM t2; +a b +1 1 +2 2 +3 3 +4 4 +5 5 +DROP TABLE t1, t2; +# +# Test of ALTER TABLE, reordering columns. +# +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b INT ); +ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_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 NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, c TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_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 NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_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; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp NULL DEFAULT NULL, + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, b TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp NULL DEFAULT NULL, + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(), b INT, c TIMESTAMP NULL ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `b` int(11) DEFAULT NULL, + `c` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_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, + `c` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(), b INT, c TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY c TIMESTAMP NULL FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp NULL DEFAULT NULL, + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b INT, c TIMESTAMP NULL ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `b` int(11) DEFAULT NULL, + `c` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 MODIFY a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_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, + `c` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b INT, c TIMESTAMP NULL ); +ALTER TABLE t1 MODIFY c TIMESTAMP NULL FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp NULL DEFAULT NULL, + `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# Test of ALTER TABLE, adding columns. +# +CREATE TABLE t1 ( a INT ); +ALTER TABLE t1 ADD COLUMN b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# Test of INSERT SELECT. +# +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +d DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE TABLE t2 ( +placeholder1 INT, +placeholder2 INT, +placeholder3 INT, +placeholder4 INT, +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', +c DATETIME, +d DATETIME +); +# 1977-08-16 15:30:01 UTC +SET TIMESTAMP = 240589801.654312; +INSERT INTO t2 (a, b, c, d) VALUES ( +'1977-08-16 15:30:01.123456', +'1977-08-16 15:30:01.234567', +'1977-08-16 15:30:01.345678', +'1977-08-16 15:30:01.456789' +); +# 1986-09-27 01:00:00 UTC +SET TIMESTAMP = 528166800.132435; +INSERT INTO t1 ( a, c ) SELECT a, c FROM t2; +SELECT * FROM t1; +a b c d +1977-08-16 15:30:01 1986-09-27 01:00:00 1977-08-16 15:30:01 1986-09-27 01:00:00 +DROP TABLE t1, t2; +# +# Test of CREATE TABLE SELECT. +# +# We test that the columns of the source table are not used to determine +# function defaults for the receiving table. +# +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.657898; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +e TIMESTAMP NULL, +f DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +g DATETIME DEFAULT CURRENT_TIMESTAMP, +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME NULL, +j DATETIME DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.164937; +CREATE TABLE t2 SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t2; +a +1970-04-11 20:13:57 +CREATE TABLE t3 SELECT b FROM t1; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t3; +b +1970-04-11 20:13:57 +CREATE TABLE t4 SELECT c FROM t1; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t4; +c +0000-00-00 00:00:00 +CREATE TABLE t5 SELECT d FROM t1; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `d` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t5; +d +1986-09-27 03:00:00 +CREATE TABLE t6 SELECT e FROM t1; +SHOW CREATE TABLE t6; +Table Create Table +t6 CREATE TABLE `t6` ( + `e` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t6; +e +NULL +CREATE TABLE t7 SELECT f FROM t1; +SHOW CREATE TABLE t7; +Table Create Table +t7 CREATE TABLE `t7` ( + `f` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t7; +f +1970-04-11 20:13:57 +CREATE TABLE t8 SELECT g FROM t1; +SHOW CREATE TABLE t8; +Table Create Table +t8 CREATE TABLE `t8` ( + `g` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t8; +g +1970-04-11 20:13:57 +CREATE TABLE t9 SELECT h FROM t1; +SHOW CREATE TABLE t9; +Table Create Table +t9 CREATE TABLE `t9` ( + `h` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t9; +h +NULL +CREATE TABLE t10 SELECT i FROM t1; +SHOW CREATE TABLE t10; +Table Create Table +t10 CREATE TABLE `t10` ( + `i` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t10; +i +NULL +CREATE TABLE t11 SELECT j FROM t1; +SHOW CREATE TABLE t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `j` datetime DEFAULT '1986-09-27 03:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t11; +j +1986-09-27 03:00:00 +CREATE TABLE t12 ( +k TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +l TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +m TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +n TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +o TIMESTAMP NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +p TIMESTAMP NULL, +q DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +r DATETIME DEFAULT CURRENT_TIMESTAMP, +s DATETIME ON UPDATE CURRENT_TIMESTAMP, +t DATETIME NULL, +u DATETIME DEFAULT '1986-09-27 03:00:00.098765' +) +SELECT * FROM t1; +SHOW CREATE TABLE t12; +Table Create Table +t12 CREATE TABLE `t12` ( + `k` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `l` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `m` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `n` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `o` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00', + `p` timestamp NULL DEFAULT NULL, + `q` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `r` datetime DEFAULT CURRENT_TIMESTAMP, + `s` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + `t` datetime DEFAULT NULL, + `u` datetime DEFAULT '1986-09-27 03:00:00', + `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` timestamp NOT NULL DEFAULT '1986-09-27 03:00:00', + `e` timestamp NULL DEFAULT NULL, + `f` datetime DEFAULT NULL, + `g` datetime DEFAULT NULL, + `h` datetime DEFAULT NULL, + `i` datetime DEFAULT NULL, + `j` datetime DEFAULT '1986-09-27 03:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12; +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.164953; +CREATE TABLE t1 ( +a DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b DATETIME DEFAULT CURRENT_TIMESTAMP, +c DATETIME ON UPDATE CURRENT_TIMESTAMP, +d DATETIME NULL, +e DATETIME DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +# 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.915736; +CREATE TABLE t2 SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t2; +a +1970-04-11 20:13:57 +CREATE TABLE t3 SELECT b FROM t1; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `b` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t3; +b +1970-04-11 20:13:57 +CREATE TABLE t4 SELECT c FROM t1; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t4; +c +NULL +CREATE TABLE t5 SELECT d FROM t1; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `d` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t5; +d +NULL +CREATE TABLE t6 SELECT e FROM t1; +SHOW CREATE TABLE t6; +Table Create Table +t6 CREATE TABLE `t6` ( + `e` datetime DEFAULT '1986-09-27 03:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t6; +e +1986-09-27 03:00:00 +DROP TABLE t1, t2, t3, t4, t5, t6; +# +# Test of a CREATE TABLE SELECT that also declared columns. In this case +# the function default should be de-activated during the execution of the +# CREATE TABLE statement. +# +# 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.987654; +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES ( 1 ), ( 2 ); +CREATE TABLE t2 ( b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SET TIMESTAMP = 2000.876543; +INSERT INTO t2( a ) VALUES ( 3 ); +SELECT * FROM t2; +b a +0000-00-00 00:00:00 1 +0000-00-00 00:00:00 2 +1970-01-01 00:33:20 3 +DROP TABLE t1, t2; +# +# Test of updating a view. +# +CREATE TABLE t1 ( a INT, b DATETIME DEFAULT CURRENT_TIMESTAMP ); +CREATE TABLE t2 ( a INT, b DATETIME ON UPDATE CURRENT_TIMESTAMP ); +CREATE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` latin1 latin1_swedish_ci +CREATE VIEW v2 AS SELECT * FROM t2; +SHOW CREATE VIEW v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` latin1 latin1_swedish_ci +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.348564; +INSERT INTO v1 ( a ) VALUES ( 1 ); +INSERT INTO v2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b +1 1971-01-31 20:13:57 +SELECT * FROM v1; +a b +1 1971-01-31 20:13:57 +SELECT * FROM t2; +a b +1 NULL +SELECT * FROM v2; +a b +1 NULL +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.567332; +UPDATE v1 SET a = 2; +UPDATE v2 SET a = 2; +SELECT * FROM t1; +a b +2 1971-01-31 20:13:57 +SELECT * FROM v1; +a b +2 1971-01-31 20:13:57 +SELECT * FROM t2; +a b +2 1970-04-11 20:13:57 +SELECT * FROM v2; +a b +2 1970-04-11 20:13:57 +DROP VIEW v1, v2; +DROP TABLE t1, t2; +# +# Test with stored procedures. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NULL, +f DATETIME DEFAULT CURRENT_TIMESTAMP, +g DATETIME ON UPDATE CURRENT_TIMESTAMP +); +CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 ); +CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1; +# 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.876544; +CALL p1(); +SELECT * FROM t1; +a b c d e f g +1 1971-01-31 20:13:57 1971-01-31 20:13:57 0000-00-00 00:00:00 NULL 1971-01-31 20:13:57 NULL +# 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.143546; +CALL p2(); +SELECT * FROM t1; +a b c d e f g +2 1970-04-11 20:13:57 1971-01-31 20:13:57 1970-04-11 20:13:57 NULL 1971-01-31 20:13:57 1970-04-11 20:13:57 +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; +# +# Test with triggers. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NULL, +f DATETIME, +g DATETIME DEFAULT CURRENT_TIMESTAMP, +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE TABLE t2 ( a INT ); +CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN +INSERT INTO t1 ( a ) VALUES ( 1 ); +END| +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.978675; +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1971-01-31 20:13:57 1971-01-31 20:13:57 0000-00-00 00:00:00 NULL NULL 1971-01-31 20:13:57 NULL 1971-01-31 20:13:57 +DROP TRIGGER t2_trg; +CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN +UPDATE t1 SET a = 2; +END| +# 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.456789; +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +2 1970-04-11 20:13:57 1971-01-31 20:13:57 1970-04-11 20:13:57 NULL NULL 1971-01-31 20:13:57 1970-04-11 20:13:57 1970-04-11 20:13:57 +DROP TABLE t1, t2; +# +# Test where the assignment target is not a column. +# +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); +CREATE TABLE t2 ( a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); +CREATE TABLE t3 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP ); +CREATE TABLE t4 ( a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP ); +CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1; +CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2; +CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3; +CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4; +INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t1; +a +2007-10-24 00:03:34 +INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t2; +a +2007-10-24 00:03:34 +INSERT INTO t3 VALUES (); +UPDATE v3 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t3; +a +2007-10-24 00:03:34 +INSERT INTO t4 VALUES (); +UPDATE v4 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t4; +a +2007-10-24 00:03:34 +DROP VIEW v1, v2, v3, v4; +DROP TABLE t1, t2, t3, t4; +# +# Test of LOAD DATA/XML INFILE +# This tests behavior of function defaults for TIMESTAMP and DATETIME +# columns. during LOAD ... INFILE. +# As can be seen here, a TIMESTAMP column with only ON UPDATE +# CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD +# ... INFILE if the value is missing. For DATETIME columns a NULL value +# is inserted instead. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +f DATETIME, +g DATETIME DEFAULT CURRENT_TIMESTAMP, +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE TABLE t2 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +c TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +d TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +e DATETIME NOT NULL, +f DATETIME NOT NULL DEFAULT '1977-01-02 12:13:14', +g DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, +h DATETIME ON UPDATE CURRENT_TIMESTAMP NOT NULL, +i DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL +); +SELECT 1 INTO OUTFILE 't3.dat' FROM dual; +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +INTO OUTFILE 't4.dat' +FROM dual; +SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual; +# Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.918273; +LOAD DATA INFILE 't3.dat' INTO TABLE t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT * FROM t1; +a 1 +b 2011-08-01 15:11:19 +c 2011-08-01 15:11:19 +d 2011-08-01 15:11:19 +e 2011-08-01 15:11:19 +f NULL +g NULL +h NULL +i NULL +LOAD DATA INFILE 't4.dat' INTO TABLE t2; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'e' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'f' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'g' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'h' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT a FROM t2; +a +2011-08-01 15:11:19 +SELECT b FROM t2; +b +2011-08-01 15:11:19 +SELECT c FROM t2; +c +2011-08-01 15:11:19 +SELECT d FROM t2; +d +2011-08-01 15:11:19 +# As shown here, supplying a NULL value to a non-nullable +# column with no default value results in the zero date. +SELECT e FROM t2; +e +0000-00-00 00:00:00 +# As shown here, supplying a NULL value to a non-nullable column with a +# default value results in the zero date. +SELECT f FROM t2; +f +0000-00-00 00:00:00 +# As shown here, supplying a NULL value to a non-nullable column with a +# default function results in the zero date. +SELECT g FROM t2; +g +0000-00-00 00:00:00 +# As shown here, supplying a NULL value to a non-nullable DATETIME ON +# UPDATE CURRENT_TIMESTAMP column with no default value results in the +# zero date. +SELECT h FROM t2; +h +0000-00-00 00:00:00 +SELECT i FROM t2; +i +0000-00-00 00:00:00 +DELETE FROM t1; +DELETE FROM t2; +# Read t3 file into t1 +# The syntax will cause a different code path to be taken +# (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command +# above. The code in this path is copy-pasted code from the path taken +# under the syntax used in the previous LOAD command. +LOAD DATA INFILE 't3.dat' INTO TABLE t1 +FIELDS TERMINATED BY '' ENCLOSED BY ''; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT b FROM t1; +b +2011-08-01 15:11:19 +SELECT c FROM t1; +c +2011-08-01 15:11:19 +SELECT d FROM t1; +d +2011-08-01 15:11:19 +SELECT e FROM t1; +e +2011-08-01 15:11:19 +# Yes, a missing field cannot be NULL using this syntax, so it will +# zero date instead. Says a comment in read_fixed_length() : "No fields +# specified in fields_vars list can be NULL in this format." +# It appears to be by design. This is inconsistent with LOAD DATA INFILE +# syntax in previous test. +SELECT f FROM t1; +f +0000-00-00 00:00:00 +SELECT g FROM t1; +g +0000-00-00 00:00:00 +# See comment above "SELECT f FROM f1". +SELECT h FROM t1; +h +0000-00-00 00:00:00 +SELECT i FROM t1; +i +0000-00-00 00:00:00 +DELETE FROM t1; +LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy ); +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19 2011-08-01 15:11:19 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 +SELECT @dummy; +@dummy +2 +DELETE FROM t1; +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10'; +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19 2005-06-06 08:09:10 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 NULL 2011-08-01 15:11:19 +DELETE FROM t1; +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10'; +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19 2011-08-01 15:11:19 0000-00-00 00:00:00 2011-08-01 15:11:19 NULL 2005-06-06 08:09:10 NULL 2011-08-01 15:11:19 +DELETE FROM t1; +# Load a static XML file +LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1 +ROWS IDENTIFIED BY '<row>'; +Missing tags are treated as NULL +SELECT * FROM t1; +a 1 +b 2011-08-01 15:11:19 +c 2011-08-01 15:11:19 +d 2011-08-01 15:11:19 +e 2011-08-01 15:11:19 +f NULL +g NULL +h NULL +i NULL +DROP TABLE t1, t2; +# +# Similar LOAD DATA tests in another form +# +# All of this test portion has been run on a pre-WL5874 trunk +# (except that like_b and like_c didn't exist) and all result +# differences are a bug. +# Regarding like_b its definition is the same as b's except +# that the constant default is replaced with a function +# default. Our expectation is that like_b would behave +# like b: if b is set to NULL, or set to 0000-00-00, or set to +# its default, then the same should apply to like_b. Same for +# like_c vs c. +# Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.089786; +SELECT 1 INTO OUTFILE "file1.dat" FROM dual; +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +INTO OUTFILE "file2.dat" FROM dual; +# Too short row +CREATE TABLE t1 ( +dummy INT, +a DATETIME NULL DEFAULT NULL, +b DATETIME NULL DEFAULT "2011-11-18", +like_b DATETIME NULL DEFAULT CURRENT_TIMESTAMP, +c DATETIME NOT NULL DEFAULT "2011-11-18", +like_c DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NOT NULL DEFAULT "2011-05-03", +f TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +g TIMESTAMP NULL DEFAULT NULL, +h INT NULL, +i INT NOT NULL DEFAULT 42 +); +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime DEFAULT NULL, + `b` datetime DEFAULT '2011-11-18 00:00:00', + `like_b` datetime DEFAULT CURRENT_TIMESTAMP, + `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00', + `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00', + `f` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file1.dat" INTO table t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +# It is strange that "like_b" gets NULL when "b" gets 0. But +# this is consistent with how "a" gets NULL when "b" gets 0, +# with how "g" gets NULL when "d" gets 0, and with how "h" gets +# NULL when "i" gets 0. Looks like "DEFAULT +# <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL +# and DEFAULT NOW are changed to NULL. +SELECT * FROM t1; +dummy 1 +a NULL +b 0000-00-00 00:00:00 +like_b NULL +c 0000-00-00 00:00:00 +like_c 0000-00-00 00:00:00 +d 0000-00-00 00:00:00 +e 2011-08-01 15:11:19 +f 2011-08-01 15:11:19 +g NULL +h NULL +i 0 +delete from t1; +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime DEFAULT NULL, + `b` datetime DEFAULT '2011-11-18 00:00:00', + `like_b` datetime DEFAULT CURRENT_TIMESTAMP, + `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00', + `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00', + `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file1.dat" INTO table t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT * FROM t1; +dummy 1 +a NULL +b 0000-00-00 00:00:00 +like_b NULL +c 0000-00-00 00:00:00 +like_c 0000-00-00 00:00:00 +d 0000-00-00 00:00:00 +e 2011-08-01 15:11:19 +f NULL +g NULL +h NULL +i 0 +delete from t1; +drop table t1; +# Conclusion derived from trunk's results: +# DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00, +# DATETIME DEFAULT NULL (a) gets NULL, +# TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00, +# TIMESTAMP NULL DEFAULT NULL (g) gets NULL, +# TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL, +# TIMESTAMP NOT NULL (f before ALTER, e) gets NOW. +### Loading NULL ### +CREATE TABLE t1 ( +dummy INT, +a DATETIME NULL DEFAULT NULL, +b DATETIME NULL DEFAULT "2011-11-18", +like_b DATETIME NULL DEFAULT CURRENT_TIMESTAMP, +c DATETIME NOT NULL DEFAULT "2011-11-18", +like_c DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, +d TIMESTAMP NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP, +e TIMESTAMP NOT NULL DEFAULT "2011-05-03", +f TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +g TIMESTAMP NULL DEFAULT NULL, +h INT NULL, +i INT NOT NULL DEFAULT 42 +); +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime DEFAULT NULL, + `b` datetime DEFAULT '2011-11-18 00:00:00', + `like_b` datetime DEFAULT CURRENT_TIMESTAMP, + `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00', + `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00', + `f` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file2.dat" INTO table t1; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT * FROM t1; +dummy NULL +a NULL +b NULL +like_b NULL +c 0000-00-00 00:00:00 +like_c 0000-00-00 00:00:00 +d NULL +e 2011-08-01 15:11:19 +f 2011-08-01 15:11:19 +g NULL +h NULL +i 0 +delete from t1; +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime DEFAULT NULL, + `b` datetime DEFAULT '2011-11-18 00:00:00', + `like_b` datetime DEFAULT CURRENT_TIMESTAMP, + `c` datetime NOT NULL DEFAULT '2011-11-18 00:00:00', + `like_c` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `d` timestamp NULL DEFAULT '2011-05-03 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `e` timestamp NOT NULL DEFAULT '2011-05-03 00:00:00', + `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file2.dat" INTO table t1; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT * FROM t1; +dummy NULL +a NULL +b NULL +like_b NULL +c 0000-00-00 00:00:00 +like_c 0000-00-00 00:00:00 +d NULL +e 2011-08-01 15:11:19 +f NULL +g NULL +h NULL +i 0 +delete from t1; +# Conclusion derived from trunk's results: +# DATETIME NULL (a,b) gets NULL, +# DATETIME NOT NULL (c) gets 0000-00-00, +# TIMESTAMP NULL (d,f,g) gets NULL, +# TIMESTAMP NOT NULL (e) gets NOW. +drop table t1; +# +# Test of updatable views with check options. The option can be violated +# using ON UPDATE updates which is very strange as this offers a loophole +# in this integrity check. +# +SET TIME_ZONE = "+03:00"; +# 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.123456; +CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE = INNODB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b +1 1970-01-01 03:16:40 +CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456' +WITH CHECK OPTION; +SELECT * FROM v1; +a b +1 1970-01-01 03:16:40 +# 1970-01-01 03:33:20 +SET TIMESTAMP = 2000.000234; +UPDATE v1 SET a = 2; +ERROR HY000: CHECK OPTION failed 'test.v1' +SELECT * FROM t1; +a b +1 1970-01-01 03:16:40 +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE CURRENT_TIMESTAMP, +c INT KEY +); +# 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1 ( c ) VALUES ( 1 ); +CREATE VIEW v1 AS +SELECT * +FROM t1 +WHERE a >= '1973-08-14 09:11:22' +WITH LOCAL CHECK OPTION; +SELECT * FROM v1; +a c +1973-08-14 09:11:22 1 +SET TIMESTAMP = 1.126789; +INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2; +ERROR HY000: CHECK OPTION failed 'test.v1' +SELECT * FROM v1; +a c +1973-08-14 09:11:22 1 +DROP VIEW v1; +DROP TABLE t1; +# +# Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE +# +CREATE TABLE t1 ( +a INT, +b INT, +ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +PRIMARY KEY ( a, ts ) +) ENGINE = INNODB; +INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' ); +CREATE TABLE t2 ( a INT ) ENGINE = INNODB; +INSERT INTO t2 VALUES ( 1 ); +UPDATE t1 STRAIGHT_JOIN t2 +SET t1.b = t1.b + 1 +WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00'; +SELECT b FROM t1; +b +1 +DROP TABLE t1, t2; +# +# Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT +# CURRENT_TIMESTAMP INSERTS ZERO +# +SET timestamp = 1000; +CREATE TABLE t1 ( b INT ); +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ADD COLUMN a6 DATETIME DEFAULT NOW() ON UPDATE NOW() FIRST; +ALTER TABLE t1 ADD COLUMN a5 DATETIME DEFAULT NOW() FIRST; +ALTER TABLE t1 ADD COLUMN a4 DATETIME ON UPDATE NOW() FIRST; +ALTER TABLE t1 ADD COLUMN a3 TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE NOW() FIRST; +ALTER TABLE t1 ADD COLUMN a2 TIMESTAMP NOT NULL DEFAULT NOW() FIRST; +ALTER TABLE t1 ADD COLUMN a1 TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW() FIRST; +ALTER TABLE t1 ADD COLUMN c1 TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW() AFTER b; +ALTER TABLE t1 ADD COLUMN c2 TIMESTAMP NOT NULL DEFAULT NOW() AFTER c1; +ALTER TABLE t1 ADD COLUMN c3 TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE NOW() AFTER c2; +ALTER TABLE t1 ADD COLUMN c4 DATETIME ON UPDATE NOW() AFTER c3; +ALTER TABLE t1 ADD COLUMN c5 DATETIME DEFAULT NOW() AFTER c4; +ALTER TABLE t1 ADD COLUMN c6 DATETIME DEFAULT NOW() ON UPDATE NOW() AFTER c5; +SELECT * FROM t1; +a1 a2 a3 a4 a5 a6 b c1 c2 c3 c4 c5 c6 +0000-00-00 00:00:00 1970-01-01 03:16:40 1970-01-01 03:16:40 NULL 1970-01-01 03:16:40 1970-01-01 03:16:40 1 0000-00-00 00:00:00 1970-01-01 03:16:40 1970-01-01 03:16:40 NULL 1970-01-01 03:16:40 1970-01-01 03:16:40 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP NOT NULL DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP, b DATETIME DEFAULT NOW() ); +INSERT INTO t1 VALUES (); +SET timestamp = 1000000000; +ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3); +ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3); +SELECT * FROM t1; +a b +1970-01-01 03:16:40.000 1970-01-01 03:16:40.000 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE CURRENT_TIMESTAMP, +b DATETIME DEFAULT '1999-12-01 11:22:33' +); +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP DEFAULT NOW(); +ALTER TABLE t1 MODIFY COLUMN b DATETIME DEFAULT NOW(); +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +a b +1999-12-01 11:22:33 1999-12-01 11:22:33 +2001-09-09 04:46:40 2001-09-09 04:46:40 +DROP TABLE t1; +# +# Function defaults run 2. Six digits scale on seconds precision. +# +SET TIME_ZONE = "+00:00"; +# +# Test of errors for column data types that dont support function +# defaults. +# +CREATE TABLE t1( a BIT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a TINYINT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a SMALLINT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a MEDIUMINT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a INT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a BIGINT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a FLOAT DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a DECIMAL DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a DATE DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a TIME DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a YEAR DEFAULT CURRENT_TIMESTAMP(6) ); +ERROR 42000: Invalid default value for 'a' +CREATE TABLE t1( a BIT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a TINYINT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a SMALLINT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a MEDIUMINT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a INT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a BIGINT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a FLOAT ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a DECIMAL ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a DATE ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a TIME ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +CREATE TABLE t1( a YEAR ON UPDATE CURRENT_TIMESTAMP(6) ); +ERROR HY000: Invalid ON UPDATE clause for 'a' column +# +# Test that the default clause behaves like NOW() regarding time zones. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NULL, +e DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +h DATETIME(6) +); +# 2011-09-27 14:11:08 UTC +SET TIMESTAMP = 1317132668.654321; +SET @old_time_zone = @@TIME_ZONE; +SET TIME_ZONE = "+05:00"; +INSERT INTO t1( d, h ) VALUES ( NOW(6), NOW(6) ); +SELECT * FROM t1; +a b c d e f g h +2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 0000-00-00 00:00:00.000000 2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 2011-09-27 19:11:08.654321 NULL 2011-09-27 19:11:08.654321 +# 1989-05-13 01:02:03 +SET TIMESTAMP = 611017323.543212; +UPDATE t1 SET d = NOW(6), h = NOW(6); +SELECT * FROM t1; +a b c d e f g h +1989-05-13 04:02:03.543212 2011-09-27 19:11:08.654321 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212 2011-09-27 19:11:08.654321 1989-05-13 04:02:03.543212 1989-05-13 04:02:03.543212 +SET TIME_ZONE = @old_time_zone; +DROP TABLE t1; +# +# Test of several TIMESTAMP columns with different function defaults. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +f INT +); +# 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; +INSERT INTO t1 ( f ) VALUES (1); +SELECT * FROM t1; +a b c d e f +2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 0000-00-00 00:00:00.000000 0000-00-00 00:00:00.000000 1 +# 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798.132435; +UPDATE t1 SET f = 2; +SELECT * FROM t1; +a b c d e f +2011-04-19 07:23:18.132435 2011-04-19 07:23:18.132435 2011-04-19 07:22:02.534231 2011-04-19 07:23:18.132435 2011-04-19 07:23:18.132435 2 +DROP TABLE t1; +# +# Test of inserted values out of order. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NULL, +f DATETIME(6), +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +j INT +); +# 2011-04-19 07:22:02 UTC +SET TIMESTAMP = 1303197722.534231; +INSERT INTO t1 ( j, a ) VALUES ( 1, 1 ); +SELECT * FROM t1; +a b c d e f g h i j +1 2011-04-19 07:22:02.534231 2011-04-19 07:22:02.534231 0000-00-00 00:00:00.000000 NULL NULL 2011-04-19 07:22:02.534231 NULL 2011-04-19 07:22:02.534231 1 +DROP TABLE t1; +# +# Test of ON DUPLICATE KEY UPDATE +# +CREATE TABLE t1 ( +a INT PRIMARY KEY, +b INT, +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +f TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +g TIMESTAMP(6) NULL, +h DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +j DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +k DATETIME(6) NULL, +l DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765' +); +# 1977-12-21 23:00:00 UTC +SET TIMESTAMP = 251593200.192837; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 NULL 1977-12-21 23:00:00.192837 1977-12-21 23:00:00.192837 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 1977-12-21 23:00:00.192837 1977-12-21 23:00:00.192837 NULL NULL 1986-09-27 03:00:00.098765 +# 1975-05-21 23:00:00 UTC +SET TIMESTAMP = 169945200.918273; +INSERT INTO t1(a) VALUES (1) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 2 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 1986-09-27 03:00:00.098765 NULL 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 NULL 1986-09-27 03:00:00.098765 +# 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1(a) VALUES (2) ON DUPLICATE KEY UPDATE b = 2; +SELECT * FROM t1; +a b c d e f g h i j k l +1 2 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 1986-09-27 03:00:00.098765 NULL 1975-05-21 23:00:00.918273 1977-12-21 23:00:00.192837 1975-05-21 23:00:00.918273 NULL 1986-09-27 03:00:00.098765 +2 NULL 1973-08-14 09:11:22.534231 1973-08-14 09:11:22.534231 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 1973-08-14 09:11:22.534231 1973-08-14 09:11:22.534231 NULL NULL 1986-09-27 03:00:00.098765 +DROP TABLE t1; +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) ); +# 2011-04-19 07:23:18 UTC +SET TIMESTAMP = 1303197798.945156; +INSERT INTO t1 VALUES +(1, 0, '2001-01-01 01:01:01.111111'), +(2, 0, '2002-02-02 02:02:02.222222'), +(3, 0, '2003-03-03 03:03:03.333333'); +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01.111111 +2 0 2002-02-02 02:02:02.222222 +3 0 2003-03-03 03:03:03.333333 +UPDATE t1 SET b = 2, c = c WHERE a = 2; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01.111111 +2 2 2002-02-02 02:02:02.222222 +3 0 2003-03-03 03:03:03.333333 +INSERT INTO t1 (a) VALUES (4); +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01.111111 +2 2 2002-02-02 02:02:02.222222 +3 0 2003-03-03 03:03:03.333333 +4 NULL 2011-04-19 07:23:18.945156 +UPDATE t1 SET c = '2004-04-04 04:04:04.444444' WHERE a = 4; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01.111111 +2 2 2002-02-02 02:02:02.222222 +3 0 2003-03-03 03:03:03.333333 +4 NULL 2004-04-04 04:04:04.444444 +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.111111 +2 2 2002-02-02 02:02:02.222222 +3 3 2003-03-03 03:03:03.333333 +4 NULL 2004-04-04 04:04:04.444444 +5 NULL 2011-04-19 07:23:18.945156 +INSERT INTO t1 (a, c) VALUES +(4, '2004-04-04 00:00:00.444444'), +(6, '2006-06-06 06:06:06.666666') +ON DUPLICATE KEY UPDATE b = 4; +SELECT * FROM t1; +a b c +1 0 2001-01-01 01:01:01.111111 +2 2 2002-02-02 02:02:02.222222 +3 3 2003-03-03 03:03:03.333333 +4 4 2011-04-19 07:23:18.945156 +5 NULL 2011-04-19 07:23:18.945156 +6 NULL 2006-06-06 06:06:06.666666 +DROP TABLE t1; +# +# Test of REPLACE INTO executed as UPDATE. +# +CREATE TABLE t1 ( +a INT PRIMARY KEY, +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +e DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +f TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +h TIMESTAMP(6) NULL, +i DATETIME(6) +); +# 1970-09-21 09:11:12 UTC +SET TIMESTAMP = 22756272.163584; +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 1970-09-21 09:11:12.163584 0000-00-00 00:00:00.000000 NULL NULL NULL +# 1970-11-10 14:16:17 UTC +SET TIMESTAMP = 27094577.852954; +REPLACE INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 1970-11-10 14:16:17.852954 0000-00-00 00:00:00.000000 NULL NULL NULL +DROP TABLE t1; +# +# Test of insertion of NULL, DEFAULT and an empty row for DEFAULT +# CURRENT_TIMESTAMP. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.163578; +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.163578 NULL 1 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 2 +2011-04-20 09:53:41.163578 NULL 3 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 4 +SET TIME_ZONE = "+03:00"; +SELECT * FROM t1; +a b c +2011-04-20 12:53:41.163578 NULL 1 +2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 2 +2011-04-20 12:53:41.163578 NULL 3 +2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 4 +SET TIME_ZONE = "+00:00"; +DROP TABLE t1; +# 2011-04-20 07:05:39 UTC +SET TIMESTAMP = 1303283139.195624; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT '2010-10-11 12:34:56' ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) 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.195624 NULL +2010-10-11 12:34:56.000000 2010-10-11 12:34:56.000000 +2011-04-20 07:05:39.195624 NULL +2010-10-11 12:34:56.000000 2010-10-11 12:34:56.000000 +DROP TABLE t1; +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.136952; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +e TIMESTAMP(6) NULL, +f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) NULL, +j DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +INSERT INTO t1 SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL; +SELECT * FROM t1; +a b c d e f g h i j +2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 0000-00-00 00:00:00.000000 1986-09-27 03:00:00.098765 NULL 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 NULL NULL 1986-09-27 03:00:00.098765 +2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 NULL NULL NULL NULL NULL NULL +DROP TABLE t1; +# +# Test of multiple-table UPDATE for DEFAULT CURRENT_TIMESTAMP +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +c INT +); +INSERT INTO t1 ( c ) VALUES (1); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 1 +# 2011-04-20 17:06:13 UTC +SET TIMESTAMP = 1303311973.163587; +UPDATE t1 t11, t1 t12 SET t11.c = 1; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.136952 2011-04-20 09:53:41.136952 1 +UPDATE t1 t11, t1 t12 SET t11.c = 2; +SELECT * FROM t1; +a b c +2011-04-20 15:06:13.163587 2011-04-20 09:53:41.136952 2 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +d DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +e INT +); +CREATE TABLE t2 ( +f INT, +g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +h DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +i TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +j TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) +); +# 1995-03-11 00:02:03 UTC +SET TIMESTAMP = 794880123.195676; +INSERT INTO t1 ( e ) VALUES ( 1 ), ( 2 ); +INSERT INTO t2 ( f ) VALUES ( 1 ), ( 2 ); +SELECT * FROM t1; +a b c d e +1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 NULL 1 +1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 NULL 2 +SELECT * FROM t2; +f g h i j +1 NULL 1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 +2 NULL 1995-03-11 00:02:03.195676 0000-00-00 00:00:00.000000 1995-03-11 00:02:03.195676 +# 1980-12-13 02:02:01 UTC +SET TIMESTAMP = 345520921.196755; +UPDATE t1, t2 SET t1.e = 3, t2.f = 4; +SELECT * FROM t1; +a b c d e +1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 3 +1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 3 +SELECT * FROM t2; +f g h i j +4 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 +4 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 1980-12-13 02:02:01.196755 1995-03-11 00:02:03.195676 +DROP TABLE t1, t2; +# +# Test of multiple table update with temporary table and on the fly. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +c INT, +d INT +); +CREATE TABLE t2 ( +a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +c INT KEY, +d INT +); +INSERT INTO t1 ( c ) VALUES (1), (2); +INSERT INTO t2 ( c ) VALUES (1), (2); +# Test of multiple table update done on the fly +# 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.194685; +UPDATE t1 JOIN t2 USING ( c ) SET t2.d = 1; +SELECT * FROM t1; +a b c d +0000-00-00 00:00:00.000000 NULL 1 NULL +0000-00-00 00:00:00.000000 NULL 2 NULL +SELECT * FROM t2; +a b c d +2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 1 1 +2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 2 1 +# Test of multiple table update done with temporary table. +# 1979-01-15 03:02:01 +SET TIMESTAMP = 285213721.134679; +UPDATE t1 JOIN t2 USING ( c ) SET t1.d = 1; +SELECT * FROM t1; +a b c d +1979-01-15 02:02:01.134679 1979-01-15 02:02:01.134679 1 1 +1979-01-15 02:02:01.134679 1979-01-15 02:02:01.134679 2 1 +SELECT * FROM t2; +a b c d +2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 1 1 +2011-04-20 15:06:13.194685 2011-04-20 15:06:13.194685 2 1 +DROP TABLE t1, t2; +# +# Test of ON UPDATE CURRENT_TIMESTAMP. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +c INT +); +# 2011-04-20 09:53:41 UTC +SET TIMESTAMP = 1303293221.794613; +INSERT INTO t1 ( c ) VALUES ( 1 ); +SELECT * FROM t1; +a b c +0000-00-00 00:00:00.000000 NULL 1 +UPDATE t1 SET c = 1; +SELECT * FROM t1; +a b c +0000-00-00 00:00:00.000000 NULL 1 +UPDATE t1 SET c = 2; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 +# +# Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP +# +# 2011-04-20 15:06:13 UTC +SET TIMESTAMP = 1303311973.534231; +UPDATE t1 t11, t1 t12 SET t11.c = 2; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; +a b c +2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 3 +DROP TABLE t1; +# +# Test of a multiple-table update where only one table is updated and +# the updated table has a primary key. +# +CREATE TABLE t1 ( a INT, b INT, PRIMARY KEY (a) ); +INSERT INTO t1 VALUES (1, 1),(2, 2),(3, 3),(4, 4); +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5); +UPDATE t1, t2 SET t1.b = 100 WHERE t1.a = t2.a; +SELECT * FROM t1; +a b +1 100 +2 100 +3 100 +4 100 +SELECT * FROM t2; +a b +1 1 +2 2 +3 3 +4 4 +5 5 +DROP TABLE t1, t2; +# +# Test of ALTER TABLE, reordering columns. +# +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT ); +ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), c TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `a` int(11) DEFAULT NULL, + `c` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp(6) NULL DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), b TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` timestamp(6) NULL DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6), b INT, c TIMESTAMP(6) NULL ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `b` int(11) DEFAULT NULL, + `c` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `c` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6), b INT, c TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY c TIMESTAMP(6) NULL FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp(6) NULL DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT, c TIMESTAMP(6) NULL ); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `b` int(11) DEFAULT NULL, + `c` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 MODIFY a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6) AFTER b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `c` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b INT, c TIMESTAMP(6) NULL ); +ALTER TABLE t1 MODIFY c TIMESTAMP(6) NULL FIRST; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` timestamp(6) NULL DEFAULT NULL, + `a` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# Test of ALTER TABLE, adding columns. +# +CREATE TABLE t1 ( a INT ); +ALTER TABLE t1 ADD COLUMN b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# Test of INSERT SELECT. +# +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +d DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +); +CREATE TABLE t2 ( +placeholder1 INT, +placeholder2 INT, +placeholder3 INT, +placeholder4 INT, +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00', +c DATETIME(6), +d DATETIME(6) +); +# 1977-08-16 15:30:01 UTC +SET TIMESTAMP = 240589801.654312; +INSERT INTO t2 (a, b, c, d) VALUES ( +'1977-08-16 15:30:01.123456', +'1977-08-16 15:30:01.234567', +'1977-08-16 15:30:01.345678', +'1977-08-16 15:30:01.456789' +); +# 1986-09-27 01:00:00 UTC +SET TIMESTAMP = 528166800.132435; +INSERT INTO t1 ( a, c ) SELECT a, c FROM t2; +SELECT * FROM t1; +a b c d +1977-08-16 15:30:01.123456 1986-09-27 01:00:00.132435 1977-08-16 15:30:01.345678 1986-09-27 01:00:00.132435 +DROP TABLE t1, t2; +# +# Test of CREATE TABLE SELECT. +# +# We test that the columns of the source table are not used to determine +# function defaults for the receiving table. +# +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.657898; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +e TIMESTAMP(6) NULL, +f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) NULL, +j DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.164937; +CREATE TABLE t2 SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t2; +a +1970-04-11 20:13:57.657897 +CREATE TABLE t3 SELECT b FROM t1; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `b` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t3; +b +1970-04-11 20:13:57.657897 +CREATE TABLE t4 SELECT c FROM t1; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t4; +c +0000-00-00 00:00:00.000000 +CREATE TABLE t5 SELECT d FROM t1; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `d` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t5; +d +1986-09-27 03:00:00.098765 +CREATE TABLE t6 SELECT e FROM t1; +SHOW CREATE TABLE t6; +Table Create Table +t6 CREATE TABLE `t6` ( + `e` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t6; +e +NULL +CREATE TABLE t7 SELECT f FROM t1; +SHOW CREATE TABLE t7; +Table Create Table +t7 CREATE TABLE `t7` ( + `f` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t7; +f +1970-04-11 20:13:57.657897 +CREATE TABLE t8 SELECT g FROM t1; +SHOW CREATE TABLE t8; +Table Create Table +t8 CREATE TABLE `t8` ( + `g` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t8; +g +1970-04-11 20:13:57.657897 +CREATE TABLE t9 SELECT h FROM t1; +SHOW CREATE TABLE t9; +Table Create Table +t9 CREATE TABLE `t9` ( + `h` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t9; +h +NULL +CREATE TABLE t10 SELECT i FROM t1; +SHOW CREATE TABLE t10; +Table Create Table +t10 CREATE TABLE `t10` ( + `i` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t10; +i +NULL +CREATE TABLE t11 SELECT j FROM t1; +SHOW CREATE TABLE t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `j` datetime(6) DEFAULT '1986-09-27 03:00:00.098765' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t11; +j +1986-09-27 03:00:00.098765 +CREATE TABLE t12 ( +k TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +l TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +m TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +n TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +o TIMESTAMP(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', +p TIMESTAMP(6) NULL, +q DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +r DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +s DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +t DATETIME(6) NULL, +u DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765' +) +SELECT * FROM t1; +SHOW CREATE TABLE t12; +Table Create Table +t12 CREATE TABLE `t12` ( + `k` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `l` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `m` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `n` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `o` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', + `p` timestamp(6) NULL DEFAULT NULL, + `q` datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `r` datetime(6) DEFAULT CURRENT_TIMESTAMP(6), + `s` datetime(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6), + `t` datetime(6) DEFAULT NULL, + `u` datetime(6) DEFAULT '1986-09-27 03:00:00.098765', + `a` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `b` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `c` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `d` timestamp(6) NOT NULL DEFAULT '1986-09-27 03:00:00.098765', + `e` timestamp(6) NULL DEFAULT NULL, + `f` datetime(6) DEFAULT NULL, + `g` datetime(6) DEFAULT NULL, + `h` datetime(6) DEFAULT NULL, + `i` datetime(6) DEFAULT NULL, + `j` datetime(6) DEFAULT '1986-09-27 03:00:00.098765' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12; +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.164953; +CREATE TABLE t1 ( +a DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +c DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +d DATETIME(6) NULL, +e DATETIME(6) DEFAULT '1986-09-27 03:00:00.098765' +); +INSERT INTO t1 VALUES (); +# 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.915736; +CREATE TABLE t2 SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t2; +a +1970-04-11 20:13:57.164953 +CREATE TABLE t3 SELECT b FROM t1; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `b` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t3; +b +1970-04-11 20:13:57.164953 +CREATE TABLE t4 SELECT c FROM t1; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t4; +c +NULL +CREATE TABLE t5 SELECT d FROM t1; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `d` datetime(6) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t5; +d +NULL +CREATE TABLE t6 SELECT e FROM t1; +SHOW CREATE TABLE t6; +Table Create Table +t6 CREATE TABLE `t6` ( + `e` datetime(6) DEFAULT '1986-09-27 03:00:00.098765' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t6; +e +1986-09-27 03:00:00.098765 +DROP TABLE t1, t2, t3, t4, t5, t6; +# +# Test of a CREATE TABLE SELECT that also declared columns. In this case +# the function default should be de-activated during the execution of the +# CREATE TABLE statement. +# +# 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.987654; +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES ( 1 ), ( 2 ); +CREATE TABLE t2 ( b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)) SELECT a FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SET TIMESTAMP = 2000.876543; +INSERT INTO t2( a ) VALUES ( 3 ); +SELECT * FROM t2; +b a +0000-00-00 00:00:00.000000 1 +0000-00-00 00:00:00.000000 2 +1970-01-01 00:33:20.876543 3 +DROP TABLE t1, t2; +# +# Test of updating a view. +# +CREATE TABLE t1 ( a INT, b DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ); +CREATE TABLE t2 ( a INT, b DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6) ); +CREATE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` latin1 latin1_swedish_ci +CREATE VIEW v2 AS SELECT * FROM t2; +SHOW CREATE VIEW v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b` from `t2` latin1 latin1_swedish_ci +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.348564; +INSERT INTO v1 ( a ) VALUES ( 1 ); +INSERT INTO v2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b +1 1971-01-31 20:13:57.348564 +SELECT * FROM v1; +a b +1 1971-01-31 20:13:57.348564 +SELECT * FROM t2; +a b +1 NULL +SELECT * FROM v2; +a b +1 NULL +# 1970-04-11 20:13:57 UTC +SET TIMESTAMP = 8712837.567332; +UPDATE v1 SET a = 2; +UPDATE v2 SET a = 2; +SELECT * FROM t1; +a b +2 1971-01-31 20:13:57.348564 +SELECT * FROM v1; +a b +2 1971-01-31 20:13:57.348564 +SELECT * FROM t2; +a b +2 1970-04-11 20:13:57.567332 +SELECT * FROM v2; +a b +2 1970-04-11 20:13:57.567332 +DROP VIEW v1, v2; +DROP TABLE t1, t2; +# +# Test with stored procedures. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NULL, +f DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +g DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6) +); +CREATE PROCEDURE p1() INSERT INTO test.t1( a ) VALUES ( 1 ); +CREATE PROCEDURE p2() UPDATE t1 SET a = 2 WHERE a = 1; +# 1971-01-31 20:13:57 UTC +SET TIMESTAMP = 34200837.876544; +CALL p1(); +SELECT * FROM t1; +a b c d e f g +1 1971-01-31 20:13:57.876544 1971-01-31 20:13:57.876544 0000-00-00 00:00:00.000000 NULL 1971-01-31 20:13:57.876544 NULL +# 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.143546; +CALL p2(); +SELECT * FROM t1; +a b c d e f g +2 1970-04-11 20:13:57.143546 1971-01-31 20:13:57.876544 1970-04-11 20:13:57.143546 NULL 1971-01-31 20:13:57.876544 1970-04-11 20:13:57.143546 +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; +# +# Test with triggers. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NULL, +f DATETIME(6), +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +); +CREATE TABLE t2 ( a INT ); +CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN +INSERT INTO t1 ( a ) VALUES ( 1 ); +END| +# 1971-01-31 21:13:57 UTC +SET TIMESTAMP = 34200837.978675; +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +1 1971-01-31 20:13:57.978675 1971-01-31 20:13:57.978675 0000-00-00 00:00:00.000000 NULL NULL 1971-01-31 20:13:57.978675 NULL 1971-01-31 20:13:57.978675 +DROP TRIGGER t2_trg; +CREATE TRIGGER t2_trg BEFORE INSERT ON t2 FOR EACH ROW +BEGIN +UPDATE t1 SET a = 2; +END| +# 1970-04-11 21:13:57 UTC +SET TIMESTAMP = 8712837.456789; +INSERT INTO t2 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b c d e f g h i +2 1970-04-11 20:13:57.456789 1971-01-31 20:13:57.978675 1970-04-11 20:13:57.456789 NULL NULL 1971-01-31 20:13:57.978675 1970-04-11 20:13:57.456789 1970-04-11 20:13:57.456789 +DROP TABLE t1, t2; +# +# Test where the assignment target is not a column. +# +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) ); +CREATE TABLE t2 ( a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) ); +CREATE TABLE t3 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6) ); +CREATE TABLE t4 ( a TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6) ); +CREATE VIEW v1 AS SELECT a COLLATE latin1_german1_ci AS b FROM t1; +CREATE VIEW v2 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t2; +CREATE VIEW v3 AS SELECT a COLLATE latin1_german1_ci AS b FROM t3; +CREATE VIEW v4 ( b ) AS SELECT a COLLATE latin1_german1_ci FROM t4; +INSERT INTO v1 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t1; +a +2007-10-24 00:03:34.010203 +INSERT INTO v2 ( b ) VALUES ( '2007-10-24 00:03:34.010203' ); +SELECT a FROM t2; +a +2007-10-24 00:03:34.010203 +INSERT INTO t3 VALUES (); +UPDATE v3 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t3; +a +2007-10-24 00:03:34.010203 +INSERT INTO t4 VALUES (); +UPDATE v4 SET b = '2007-10-24 00:03:34.010203'; +SELECT a FROM t4; +a +2007-10-24 00:03:34.010203 +DROP VIEW v1, v2, v3, v4; +DROP TABLE t1, t2, t3, t4; +# +# Test of LOAD DATA/XML INFILE +# This tests behavior of function defaults for TIMESTAMP and DATETIME +# columns. during LOAD ... INFILE. +# As can be seen here, a TIMESTAMP column with only ON UPDATE +# CURRENT_TIMESTAMP will still have CURRENT_TIMESTAMP inserted on LOAD +# ... INFILE if the value is missing. For DATETIME columns a NULL value +# is inserted instead. +# +CREATE TABLE t1 ( +a INT, +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +f DATETIME(6), +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +); +CREATE TABLE t2 ( +a TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +c TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +e DATETIME(6) NOT NULL, +f DATETIME(6) NOT NULL DEFAULT '1977-01-02 12:13:14', +g DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL, +h DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6) NOT NULL, +i DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) NOT NULL +); +SELECT 1 INTO OUTFILE 't3.dat' FROM dual; +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +INTO OUTFILE 't4.dat' +FROM dual; +SELECT 1, 2 INTO OUTFILE 't5.dat' FROM dual; +# Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.918273; +LOAD DATA INFILE 't3.dat' INTO TABLE t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT * FROM t1; +a 1 +b 2011-08-01 15:11:19.918273 +c 2011-08-01 15:11:19.918273 +d 2011-08-01 15:11:19.918273 +e 2011-08-01 15:11:19.918273 +f NULL +g NULL +h NULL +i NULL +LOAD DATA INFILE 't4.dat' INTO TABLE t2; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'e' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'f' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'g' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'h' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT a FROM t2; +a +2011-08-01 15:11:19.918273 +SELECT b FROM t2; +b +2011-08-01 15:11:19.918273 +SELECT c FROM t2; +c +2011-08-01 15:11:19.918273 +SELECT d FROM t2; +d +2011-08-01 15:11:19.918273 +# As shown here, supplying a NULL value to a non-nullable +# column with no default value results in the zero date. +SELECT e FROM t2; +e +0000-00-00 00:00:00.000000 +# As shown here, supplying a NULL value to a non-nullable column with a +# default value results in the zero date. +SELECT f FROM t2; +f +0000-00-00 00:00:00.000000 +# As shown here, supplying a NULL value to a non-nullable column with a +# default function results in the zero date. +SELECT g FROM t2; +g +0000-00-00 00:00:00.000000 +# As shown here, supplying a NULL value to a non-nullable DATETIME ON +# UPDATE CURRENT_TIMESTAMP column with no default value results in the +# zero date. +SELECT h FROM t2; +h +0000-00-00 00:00:00.000000 +SELECT i FROM t2; +i +0000-00-00 00:00:00.000000 +DELETE FROM t1; +DELETE FROM t2; +# Read t3 file into t1 +# The syntax will cause a different code path to be taken +# (read_fixed_length()) than under the LOAD ... INTO TABLE t1 command +# above. The code in this path is copy-pasted code from the path taken +# under the syntax used in the previous LOAD command. +LOAD DATA INFILE 't3.dat' INTO TABLE t1 +FIELDS TERMINATED BY '' ENCLOSED BY ''; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT b FROM t1; +b +2011-08-01 15:11:19.918273 +SELECT c FROM t1; +c +2011-08-01 15:11:19.918273 +SELECT d FROM t1; +d +2011-08-01 15:11:19.918273 +SELECT e FROM t1; +e +2011-08-01 15:11:19.918273 +# Yes, a missing field cannot be NULL using this syntax, so it will +# zero date instead. Says a comment in read_fixed_length() : "No fields +# specified in fields_vars list can be NULL in this format." +# It appears to be by design. This is inconsistent with LOAD DATA INFILE +# syntax in previous test. +SELECT f FROM t1; +f +0000-00-00 00:00:00.000000 +SELECT g FROM t1; +g +0000-00-00 00:00:00.000000 +# See comment above "SELECT f FROM f1". +SELECT h FROM t1; +h +0000-00-00 00:00:00.000000 +SELECT i FROM t1; +i +0000-00-00 00:00:00.000000 +DELETE FROM t1; +LOAD DATA INFILE 't5.dat' INTO TABLE t1 ( a, @dummy ); +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19.918273 2011-08-01 15:11:19.918273 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 +SELECT @dummy; +@dummy +2 +DELETE FROM t1; +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET c = '2005-06-06 08:09:10'; +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19.918273 2005-06-06 08:09:10.000000 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 NULL 2011-08-01 15:11:19.918273 +DELETE FROM t1; +LOAD DATA INFILE 't3.dat' INTO TABLE t1 ( a ) SET g = '2005-06-06 08:09:10'; +SELECT * FROM t1; +a b c d e f g h i +1 2011-08-01 15:11:19.918273 2011-08-01 15:11:19.918273 0000-00-00 00:00:00.000000 2011-08-01 15:11:19.918273 NULL 2005-06-06 08:09:10.000000 NULL 2011-08-01 15:11:19.918273 +DELETE FROM t1; +# Load a static XML file +LOAD XML INFILE '../../std_data/onerow.xml' INTO TABLE t1 +ROWS IDENTIFIED BY '<row>'; +Missing tags are treated as NULL +SELECT * FROM t1; +a 1 +b 2011-08-01 15:11:19.918273 +c 2011-08-01 15:11:19.918273 +d 2011-08-01 15:11:19.918273 +e 2011-08-01 15:11:19.918273 +f NULL +g NULL +h NULL +i NULL +DROP TABLE t1, t2; +# +# Similar LOAD DATA tests in another form +# +# All of this test portion has been run on a pre-WL5874 trunk +# (except that like_b and like_c didn't exist) and all result +# differences are a bug. +# Regarding like_b its definition is the same as b's except +# that the constant default is replaced with a function +# default. Our expectation is that like_b would behave +# like b: if b is set to NULL, or set to 0000-00-00, or set to +# its default, then the same should apply to like_b. Same for +# like_c vs c. +# Mon Aug 1 15:11:19 2011 UTC +SET TIMESTAMP = 1312211479.089786; +SELECT 1 INTO OUTFILE "file1.dat" FROM dual; +SELECT NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +INTO OUTFILE "file2.dat" FROM dual; +# Too short row +CREATE TABLE t1 ( +dummy INT, +a DATETIME(6) NULL DEFAULT NULL, +b DATETIME(6) NULL DEFAULT "2011-11-18", +like_b DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), +c DATETIME(6) NOT NULL DEFAULT "2011-11-18", +like_c DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NOT NULL DEFAULT "2011-05-03", +f TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +g TIMESTAMP(6) NULL DEFAULT NULL, +h INT NULL, +i INT NOT NULL DEFAULT 42 +); +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime(6) DEFAULT NULL, + `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000', + `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6), + `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000', + `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000', + `f` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `g` timestamp(6) NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file1.dat" INTO table t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +# It is strange that "like_b" gets NULL when "b" gets 0. But +# this is consistent with how "a" gets NULL when "b" gets 0, +# with how "g" gets NULL when "d" gets 0, and with how "h" gets +# NULL when "i" gets 0. Looks like "DEFAULT +# <non-NULL-constant>" is changed to 0, whereas DEFAULT NULL +# and DEFAULT NOW are changed to NULL. +SELECT * FROM t1; +dummy 1 +a NULL +b 0000-00-00 00:00:00.000000 +like_b NULL +c 0000-00-00 00:00:00.000000 +like_c 0000-00-00 00:00:00.000000 +d 0000-00-00 00:00:00.000000 +e 2011-08-01 15:11:19.089786 +f 2011-08-01 15:11:19.089786 +g NULL +h NULL +i 0 +delete from t1; +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime(6) DEFAULT NULL, + `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000', + `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6), + `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000', + `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000', + `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp(6) NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file1.dat" INTO table t1; +Warnings: +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +Warning 1261 Row 1 doesn't contain data for all columns +SELECT * FROM t1; +dummy 1 +a NULL +b 0000-00-00 00:00:00.000000 +like_b NULL +c 0000-00-00 00:00:00.000000 +like_c 0000-00-00 00:00:00.000000 +d 0000-00-00 00:00:00.000000 +e 2011-08-01 15:11:19.089786 +f NULL +g NULL +h NULL +i 0 +delete from t1; +drop table t1; +# Conclusion derived from trunk's results: +# DATETIME DEFAULT <non-NULL-constant> (b,c) gets 0000-00-00, +# DATETIME DEFAULT NULL (a) gets NULL, +# TIMESTAMP NULL DEFAULT <non-NULL-constant> (d) gets 0000-00-00, +# TIMESTAMP NULL DEFAULT NULL (g) gets NULL, +# TIMESTAMP NULL DEFAULT NOW (f after ALTER) gets NULL, +# TIMESTAMP NOT NULL (f before ALTER, e) gets NOW. +### Loading NULL ### +CREATE TABLE t1 ( +dummy INT, +a DATETIME(6) NULL DEFAULT NULL, +b DATETIME(6) NULL DEFAULT "2011-11-18", +like_b DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), +c DATETIME(6) NOT NULL DEFAULT "2011-11-18", +like_c DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +d TIMESTAMP(6) NULL DEFAULT "2011-05-03" ON UPDATE CURRENT_TIMESTAMP(6), +e TIMESTAMP(6) NOT NULL DEFAULT "2011-05-03", +f TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +g TIMESTAMP(6) NULL DEFAULT NULL, +h INT NULL, +i INT NOT NULL DEFAULT 42 +); +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime(6) DEFAULT NULL, + `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000', + `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6), + `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000', + `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000', + `f` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `g` timestamp(6) NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file2.dat" INTO table t1; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT * FROM t1; +dummy NULL +a NULL +b NULL +like_b NULL +c 0000-00-00 00:00:00.000000 +like_c 0000-00-00 00:00:00.000000 +d NULL +e 2011-08-01 15:11:19.089786 +f 2011-08-01 15:11:19.089786 +g NULL +h NULL +i 0 +delete from t1; +alter table t1 +modify f TIMESTAMP NULL default CURRENT_TIMESTAMP; +# There is no promotion +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `dummy` int(11) DEFAULT NULL, + `a` datetime(6) DEFAULT NULL, + `b` datetime(6) DEFAULT '2011-11-18 00:00:00.000000', + `like_b` datetime(6) DEFAULT CURRENT_TIMESTAMP(6), + `c` datetime(6) NOT NULL DEFAULT '2011-11-18 00:00:00.000000', + `like_c` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + `d` timestamp(6) NULL DEFAULT '2011-05-03 00:00:00.000000' ON UPDATE CURRENT_TIMESTAMP(6), + `e` timestamp(6) NOT NULL DEFAULT '2011-05-03 00:00:00.000000', + `f` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `g` timestamp(6) NULL DEFAULT NULL, + `h` int(11) DEFAULT NULL, + `i` int(11) NOT NULL DEFAULT '42' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +LOAD DATA INFILE "file2.dat" INTO table t1; +Warnings: +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'like_c' at row 1 +Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'i' at row 1 +SELECT * FROM t1; +dummy NULL +a NULL +b NULL +like_b NULL +c 0000-00-00 00:00:00.000000 +like_c 0000-00-00 00:00:00.000000 +d NULL +e 2011-08-01 15:11:19.089786 +f NULL +g NULL +h NULL +i 0 +delete from t1; +# Conclusion derived from trunk's results: +# DATETIME NULL (a,b) gets NULL, +# DATETIME NOT NULL (c) gets 0000-00-00, +# TIMESTAMP NULL (d,f,g) gets NULL, +# TIMESTAMP NOT NULL (e) gets NOW. +drop table t1; +# +# Test of updatable views with check options. The option can be violated +# using ON UPDATE updates which is very strange as this offers a loophole +# in this integrity check. +# +SET TIME_ZONE = "+03:00"; +# 1970-01-01 03:16:40 +SET TIMESTAMP = 1000.123456; +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)) ENGINE = INNODB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 ( a ) VALUES ( 1 ); +SELECT * FROM t1; +a b +1 1970-01-01 03:16:40.123456 +CREATE VIEW v1 AS SELECT * FROM t1 WHERE b <= '1970-01-01 03:16:40.123456' +WITH CHECK OPTION; +SELECT * FROM v1; +a b +1 1970-01-01 03:16:40.123456 +# 1970-01-01 03:33:20 +SET TIMESTAMP = 2000.000234; +UPDATE v1 SET a = 2; +ERROR HY000: CHECK OPTION failed 'test.v1' +SELECT * FROM t1; +a b +1 1970-01-01 03:16:40.123456 +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT '1973-08-14 09:11:22.089786' ON UPDATE CURRENT_TIMESTAMP(6), +c INT KEY +); +# 1973-08-14 09:11:22 UTC +SET TIMESTAMP = 114167482.534231; +INSERT INTO t1 ( c ) VALUES ( 1 ); +CREATE VIEW v1 AS +SELECT * +FROM t1 +WHERE a >= '1973-08-14 09:11:22' +WITH LOCAL CHECK OPTION; +SELECT * FROM v1; +a c +1973-08-14 09:11:22.089786 1 +SET TIMESTAMP = 1.126789; +INSERT INTO v1 ( c ) VALUES ( 1 ) ON DUPLICATE KEY UPDATE c = 2; +ERROR HY000: CHECK OPTION failed 'test.v1' +SELECT * FROM v1; +a c +1973-08-14 09:11:22.089786 1 +DROP VIEW v1; +DROP TABLE t1; +# +# Bug 13095459 - MULTI-TABLE UPDATE MODIFIES A ROW TWICE +# +CREATE TABLE t1 ( +a INT, +b INT, +ts TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), +PRIMARY KEY ( a, ts ) +) ENGINE = INNODB; +INSERT INTO t1( a, b, ts ) VALUES ( 1, 0, '2000-09-28 17:44:34' ); +CREATE TABLE t2 ( a INT ) ENGINE = INNODB; +INSERT INTO t2 VALUES ( 1 ); +UPDATE t1 STRAIGHT_JOIN t2 +SET t1.b = t1.b + 1 +WHERE t1.a = 1 AND t1.ts >= '2000-09-28 00:00:00'; +SELECT b FROM t1; +b +1 +DROP TABLE t1, t2; +# +# Bug#11745578: 17392: ALTER TABLE ADD COLUMN TIMESTAMP DEFAULT +# CURRENT_TIMESTAMP INSERTS ZERO +# +SET timestamp = 1000; +CREATE TABLE t1 ( b INT ); +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ADD COLUMN a6 DATETIME(6) DEFAULT NOW(6) ON UPDATE NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN a5 DATETIME(6) DEFAULT NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN a4 DATETIME(6) ON UPDATE NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN a3 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN a2 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN a1 TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6) FIRST; +ALTER TABLE t1 ADD COLUMN c1 TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE NOW(6) AFTER b; +ALTER TABLE t1 ADD COLUMN c2 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) AFTER c1; +ALTER TABLE t1 ADD COLUMN c3 TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE NOW(6) AFTER c2; +ALTER TABLE t1 ADD COLUMN c4 DATETIME(6) ON UPDATE NOW(6) AFTER c3; +ALTER TABLE t1 ADD COLUMN c5 DATETIME(6) DEFAULT NOW(6) AFTER c4; +ALTER TABLE t1 ADD COLUMN c6 DATETIME(6) DEFAULT NOW(6) ON UPDATE NOW(6) AFTER c5; +SELECT * FROM t1; +a1 a2 a3 a4 a5 a6 b c1 c2 c3 c4 c5 c6 +0000-00-00 00:00:00.000000 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 NULL 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 1 0000-00-00 00:00:00.000000 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 NULL 1970-01-01 03:16:40.000000 1970-01-01 03:16:40.000000 +DROP TABLE t1; +CREATE TABLE t1 ( a TIMESTAMP(6) NOT NULL DEFAULT NOW(6) ON UPDATE CURRENT_TIMESTAMP(6), b DATETIME(6) DEFAULT NOW(6) ); +INSERT INTO t1 VALUES (); +SET timestamp = 1000000000; +ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3); +ALTER TABLE t1 MODIFY COLUMN b DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3); +SELECT * FROM t1; +a b +1970-01-01 03:16:40.000 1970-01-01 03:16:40.000 +DROP TABLE t1; +CREATE TABLE t1 ( +a TIMESTAMP(6) NOT NULL DEFAULT '1999-12-01 11:22:33' ON UPDATE CURRENT_TIMESTAMP(6), +b DATETIME(6) DEFAULT '1999-12-01 11:22:33' +); +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY COLUMN a TIMESTAMP(6) DEFAULT NOW(6); +ALTER TABLE t1 MODIFY COLUMN b DATETIME(6) DEFAULT NOW(6); +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +a b +1999-12-01 11:22:33.000000 1999-12-01 11:22:33.000000 +2001-09-09 04:46:40.000000 2001-09-09 04:46:40.000000 +DROP TABLE t1; diff --git a/mysql-test/r/function_defaults_notembedded.result b/mysql-test/r/function_defaults_notembedded.result new file mode 100644 index 00000000000..c54ae14aef4 --- /dev/null +++ b/mysql-test/r/function_defaults_notembedded.result @@ -0,0 +1,171 @@ +# +# Test of function defaults for non-embedded server. +# +# +# Function defaults run 1. No microsecond precision. +# +SET TIME_ZONE = "+00:00"; +# +# Test of INSERT DELAYED ... SET ... +# +# 2011-04-19 08:02:40 UTC +SET TIMESTAMP = 1303200160.123456; +CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +INSERT DELAYED INTO t1 SET a = 1; +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:02:40 +SELECT * FROM t1 WHERE b = 0; +a b +INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060'; +FLUSH TABLE t1; +SELECT * FROM t1; +a b +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.234567; +CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +INSERT DELAYED INTO t1 ( a ) VALUES (1); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01 +INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123'); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01 +2 1977-12-19 12:34:56 +DROP TABLE t1; +# +# Test of a delayed insert handler servicing two insert operations +# with different sets of active defaults. +# +CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +# 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241.345678; +SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go'; +INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3); +SET debug_sync = 'now WAIT_FOR parked'; +# 2011-04-19 08:04:01 UTC +SET TIME_ZONE="+03:00"; +SET TIMESTAMP = 1303200241.456789; +INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345'); +SET debug_sync = 'now SIGNAL go'; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01 +2 2011-04-19 08:04:01 +3 2011-04-19 08:04:01 +4 1977-12-19 09:34:56 +5 1977-12-19 09:34:57 +6 1977-12-19 09:34:58 +DROP TABLE t1; +# +# Test of early activation of function defaults. +# +CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +SET TIMESTAMP = 1317235172.987654; +INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3); +SET TIMESTAMP = 385503754.876543; +INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-09-28 18:39:32 +2 2011-09-28 18:39:32 +3 2011-09-28 18:39:32 +4 1982-03-20 20:22:34 +5 1982-03-20 20:22:34 +6 1982-03-20 20:22:34 +DROP TABLE t1; +# +# Function defaults run 2. Six digits scale on seconds precision. +# +SET TIME_ZONE = "+00:00"; +# +# Test of INSERT DELAYED ... SET ... +# +# 2011-04-19 08:02:40 UTC +SET TIMESTAMP = 1303200160.123456; +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +INSERT DELAYED INTO t1 SET a = 1; +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:02:40.123456 +SELECT * FROM t1 WHERE b = 0; +a b +INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060'; +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:02:40.123456 +2 1980-01-02 10:20:30.405060 +DROP TABLE t1; +# +# Test of INSERT DELAYED ... VALUES ... +# +# 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241.234567; +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +INSERT DELAYED INTO t1 ( a ) VALUES (1); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01.234567 +INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123'); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01.234567 +2 1977-12-19 12:34:56.789123 +DROP TABLE t1; +# +# Test of a delayed insert handler servicing two insert operations +# with different sets of active defaults. +# +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +# 2011-04-19 08:04:01 UTC +SET TIMESTAMP = 1303200241.345678; +SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go'; +INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3); +SET debug_sync = 'now WAIT_FOR parked'; +# 2011-04-19 08:04:01 UTC +SET TIME_ZONE="+03:00"; +SET TIMESTAMP = 1303200241.456789; +INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345'); +SET debug_sync = 'now SIGNAL go'; +SELECT * FROM t1; +a b +1 2011-04-19 08:04:01.345678 +2 2011-04-19 08:04:01.345678 +3 2011-04-19 08:04:01.345678 +4 1977-12-19 09:34:56.789123 +5 1977-12-19 09:34:57.891234 +6 1977-12-19 09:34:58.912345 +DROP TABLE t1; +# +# Test of early activation of function defaults. +# +CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +SET TIMESTAMP = 1317235172.987654; +INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3); +SET TIMESTAMP = 385503754.876543; +INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6); +FLUSH TABLE t1; +SELECT * FROM t1; +a b +1 2011-09-28 18:39:32.987654 +2 2011-09-28 18:39:32.987654 +3 2011-09-28 18:39:32.987654 +4 1982-03-20 20:22:34.876543 +5 1982-03-20 20:22:34.876543 +6 1982-03-20 20:22:34.876543 +DROP TABLE t1; diff --git a/mysql-test/r/log_slow.result b/mysql-test/r/log_slow.result index 75e92e7a0b5..76cf45631bd 100644 --- a/mysql-test/r/log_slow.result +++ b/mysql-test/r/log_slow.result @@ -44,7 +44,7 @@ select @@log_slow_verbosity; innodb show fields from mysql.slow_log; Field Type Null Key Default Extra -start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP user_host mediumtext NO NULL query_time time(6) NO NULL lock_time time(6) NO NULL diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 62775f3db4d..dd3bee0ac88 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -53,7 +53,7 @@ ERROR HY000: You can't use locks with log tables. show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -62,7 +62,7 @@ general_log CREATE TABLE `general_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' show fields from mysql.general_log; Field Type Null Key Default Extra -event_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +event_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP user_host mediumtext NO NULL thread_id int(11) NO NULL server_id int(10) unsigned NO NULL @@ -71,7 +71,7 @@ argument mediumtext NO NULL show create table mysql.slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, @@ -85,7 +85,7 @@ slow_log CREATE TABLE `slow_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' show fields from mysql.slow_log; Field Type Null Key Default Extra -start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP user_host mediumtext NO NULL query_time time(6) NO NULL lock_time time(6) NO NULL @@ -164,7 +164,7 @@ set global slow_query_log='OFF'; show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -174,7 +174,7 @@ general_log CREATE TABLE `general_log` ( show create table mysql.slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, @@ -191,7 +191,7 @@ alter table mysql.slow_log engine=myisam; show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -201,7 +201,7 @@ general_log CREATE TABLE `general_log` ( show create table mysql.slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 7b650addd3d..ef8bcea3649 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -5239,7 +5239,7 @@ Error 1146 Table 'mysql.event' doesn't exist SHOW CREATE TABLE mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -5249,7 +5249,7 @@ general_log CREATE TABLE `general_log` ( SHOW CREATE TABLE mysql.slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index d5409136ed4..9eb617d94f7 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -242,7 +242,7 @@ event CREATE TABLE `event` ( show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` ( show create table slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result index d5409136ed4..9eb617d94f7 100644 --- a/mysql-test/r/system_mysql_db_fix40123.result +++ b/mysql-test/r/system_mysql_db_fix40123.result @@ -242,7 +242,7 @@ event CREATE TABLE `event` ( show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` ( show create table slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result index d5409136ed4..9eb617d94f7 100644 --- a/mysql-test/r/system_mysql_db_fix50030.result +++ b/mysql-test/r/system_mysql_db_fix50030.result @@ -242,7 +242,7 @@ event CREATE TABLE `event` ( show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` ( show create table slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result index d5409136ed4..9eb617d94f7 100644 --- a/mysql-test/r/system_mysql_db_fix50117.result +++ b/mysql-test/r/system_mysql_db_fix50117.result @@ -242,7 +242,7 @@ event CREATE TABLE `event` ( show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `thread_id` int(11) NOT NULL, `server_id` int(10) unsigned NOT NULL, @@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` ( show create table slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_host` mediumtext NOT NULL, `query_time` time(6) NOT NULL, `lock_time` time(6) NOT NULL, diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 52c7f05839e..e7add0d80a7 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -148,15 +148,15 @@ ix+0 20030101000000 drop table t1; create table t1 (t1 timestamp, t2 timestamp default now()); -ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause +drop table t1; create table t1 (t1 timestamp, t2 timestamp on update now()); -ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause +drop table t1; create table t1 (t1 timestamp, t2 timestamp default now() on update now()); -ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause +drop table t1; create table t1 (t1 timestamp default now(), t2 timestamp on update now()); -ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause +drop table t1; create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now()); -ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause +drop table t1; create table t1 (t1 timestamp default '2003-01-01 00:00:00', t2 datetime, t3 timestamp); SET TIMESTAMP=1000000000; insert into t1 values (); diff --git a/mysql-test/r/type_timestamp_hires.result b/mysql-test/r/type_timestamp_hires.result index 3f1e05f4870..070f3032987 100644 --- a/mysql-test/r/type_timestamp_hires.result +++ b/mysql-test/r/type_timestamp_hires.result @@ -63,15 +63,15 @@ a show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 show columns from t1; Field Type Null Key Default Extra -a timestamp(4) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +a timestamp(4) NO CURRENT_TIMESTAMP(4) on update CURRENT_TIMESTAMP select table_name, column_name, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, datetime_precision, character_set_name, collation_name, column_type, column_key, extra from information_schema.columns where table_name='t1'; table_name t1 column_name a -column_default CURRENT_TIMESTAMP +column_default CURRENT_TIMESTAMP(4) is_nullable NO data_type timestamp character_maximum_length NULL @@ -113,7 +113,7 @@ t2 CREATE TABLE `t2` ( show create table t3; Table Create Table t3 CREATE TABLE `t3` ( - `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + `a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2, t3; insert t1 values ('2010-12-13 14:15:16.222222'); diff --git a/mysql-test/std_data/onerow.xml b/mysql-test/std_data/onerow.xml new file mode 100644 index 00000000000..094dd813b2d --- /dev/null +++ b/mysql-test/std_data/onerow.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +<database name="test"> + <table_structure name="onerow"> + <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" /> + </table_structure> + <table_data name="onerow"> + <row> + <field name="a">1</field> + </row> + </table_data> +</database> +</mysqldump> diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 4eff12dab7b..2a0c9296987 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -59,7 +59,7 @@ def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) sele def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate') select,insert,update,references def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references def mysql general_log command_type 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select,insert,update,references -def mysql general_log event_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references +def mysql general_log event_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references @@ -159,7 +159,7 @@ def mysql slow_log rows_examined 6 NULL NO int NULL NULL 10 0 NULL NULL NULL int def mysql slow_log rows_sent 5 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references -def mysql slow_log start_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references +def mysql slow_log start_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references def mysql slow_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references def mysql tables_priv Column_priv 8 NO set 31 93 NULL NULL NULL utf8 utf8_general_ci set('Select','Insert','Update','References') select,insert,update,references def mysql tables_priv Db 2 NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references diff --git a/mysql-test/suite/rpl/r/rpl_function_defaults.result b/mysql-test/suite/rpl/r/rpl_function_defaults.result new file mode 100644 index 00000000000..264bb3c9c6d --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_function_defaults.result @@ -0,0 +1,132 @@ +# +# Test of function defaults on replicated tables. +# +include/master-slave.inc +[connection master] +connection master +SET TIME_ZONE="+10:30"; +SET TIMESTAMP=123456.789123; +SELECT CURRENT_TIMESTAMP; +CURRENT_TIMESTAMP +1970-01-02 20:47:36 +connection slave +SET TIME_ZONE="+00:00"; +SET TIMESTAMP=987654321.123456; +SELECT CURRENT_TIMESTAMP; +CURRENT_TIMESTAMP +2001-04-19 04:25:21 +connection master +CREATE TABLE t1 ( +a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1), +c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), +d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), +e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4), +f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5), +g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), +h DATETIME DEFAULT CURRENT_TIMESTAMP, +i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1), +j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2), +k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), +l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4), +m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5), +n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), +o INT +); +INSERT INTO t1 ( o ) VALUES ( 1 ); +CREATE TABLE t2 ( +a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1), +c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2), +d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3), +e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4), +f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5), +g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), +h DATETIME ON UPDATE CURRENT_TIMESTAMP, +i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1), +j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2), +k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), +l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4), +m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5), +n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), +o INT +); +INSERT INTO t2 ( o ) VALUES ( 1 ); +sync_slave_with_master +connection slave +SELECT * FROM t1; +a 1970-01-02 10:17:36 +b 1970-01-02 10:17:36.7 +c 1970-01-02 10:17:36.78 +d 1970-01-02 10:17:36.789 +e 1970-01-02 10:17:36.7891 +f 1970-01-02 10:17:36.78912 +g 1970-01-02 10:17:36.789123 +h 1970-01-02 20:47:36 +i 1970-01-02 20:47:36.7 +j 1970-01-02 20:47:36.78 +k 1970-01-02 20:47:36.789 +l 1970-01-02 20:47:36.7891 +m 1970-01-02 20:47:36.78912 +n 1970-01-02 20:47:36.789123 +o 1 +SELECT * FROM t2; +a 0000-00-00 00:00:00 +b 0000-00-00 00:00:00.0 +c 0000-00-00 00:00:00.00 +d 0000-00-00 00:00:00.000 +e 0000-00-00 00:00:00.0000 +f 0000-00-00 00:00:00.00000 +g 0000-00-00 00:00:00.000000 +h NULL +i NULL +j NULL +k NULL +l NULL +m NULL +n NULL +o 1 +connection master +SET TIMESTAMP=1234567890.123456; +SELECT CURRENT_TIMESTAMP; +CURRENT_TIMESTAMP +2009-02-14 10:01:30 +UPDATE t1 SET o = 2; +UPDATE t2 SET o = 2; +sync_slave_with_master +connection slave +SELECT * FROM t1; +a 1970-01-02 10:17:36 +b 1970-01-02 10:17:36.7 +c 1970-01-02 10:17:36.78 +d 1970-01-02 10:17:36.789 +e 1970-01-02 10:17:36.7891 +f 1970-01-02 10:17:36.78912 +g 1970-01-02 10:17:36.789123 +h 1970-01-02 20:47:36 +i 1970-01-02 20:47:36.7 +j 1970-01-02 20:47:36.78 +k 1970-01-02 20:47:36.789 +l 1970-01-02 20:47:36.7891 +m 1970-01-02 20:47:36.78912 +n 1970-01-02 20:47:36.789123 +o 2 +SELECT * FROM t2; +a 2009-02-13 23:31:30 +b 2009-02-13 23:31:30.1 +c 2009-02-13 23:31:30.12 +d 2009-02-13 23:31:30.123 +e 2009-02-13 23:31:30.1234 +f 2009-02-13 23:31:30.12345 +g 2009-02-13 23:31:30.123456 +h 2009-02-14 10:01:30 +i 2009-02-14 10:01:30.1 +j 2009-02-14 10:01:30.12 +k 2009-02-14 10:01:30.123 +l 2009-02-14 10:01:30.1234 +m 2009-02-14 10:01:30.12345 +n 2009-02-14 10:01:30.123456 +o 2 +connection master +DROP TABLE t1, t2; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_function_defaults.test b/mysql-test/suite/rpl/t/rpl_function_defaults.test new file mode 100644 index 00000000000..24bec10d305 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_function_defaults.test @@ -0,0 +1,93 @@ +--echo # +--echo # Test of function defaults on replicated tables. +--echo # + +source include/master-slave.inc; + +--echo connection master +connection master; +SET TIME_ZONE="+10:30"; +SET TIMESTAMP=123456.789123; +SELECT CURRENT_TIMESTAMP; + +--echo connection slave +connection slave; +SET TIME_ZONE="+00:00"; +SET TIMESTAMP=987654321.123456; +SELECT CURRENT_TIMESTAMP; + +--echo connection master +connection master; +CREATE TABLE t1 ( + a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1), + c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4), + f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5), + g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + h DATETIME DEFAULT CURRENT_TIMESTAMP, + i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1), + j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2), + k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), + l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4), + m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5), + n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), + o INT +); + +INSERT INTO t1 ( o ) VALUES ( 1 ); + +CREATE TABLE t2 ( + a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1), + c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2), + d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3), + e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4), + f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5), + g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), + h DATETIME ON UPDATE CURRENT_TIMESTAMP, + i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1), + j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2), + k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), + l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4), + m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5), + n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), + o INT +); + +INSERT INTO t2 ( o ) VALUES ( 1 ); + +--echo sync_slave_with_master +sync_slave_with_master; + +--echo connection slave +connection slave; + +query_vertical SELECT * FROM t1; +query_vertical SELECT * FROM t2; + +--echo connection master +connection master; + +SET TIMESTAMP=1234567890.123456; +SELECT CURRENT_TIMESTAMP; + +UPDATE t1 SET o = 2; +UPDATE t2 SET o = 2; + +--echo sync_slave_with_master +sync_slave_with_master; + +--echo connection slave +connection slave; + +query_vertical SELECT * FROM t1; +query_vertical SELECT * FROM t2; + +--echo connection master +connection master; + +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index d80127df860..258213620ce 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -55,10 +55,10 @@ create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # # Some wrong defaults, so these creates should fail too (Bug #5902) # ---error 1067 create table t1 (a datetime default now()); ---error 1294 +drop table t1; create table t1 (a datetime on update now()); +drop table t1; --error 1067 create table t1 (a int default 100 auto_increment); --error 1067 diff --git a/mysql-test/t/function_defaults.test b/mysql-test/t/function_defaults.test new file mode 100644 index 00000000000..dd29b4609cb --- /dev/null +++ b/mysql-test/t/function_defaults.test @@ -0,0 +1,23 @@ +--echo # +--echo # Test of function defaults for any server, including embedded. +--echo # + +--source include/have_innodb.inc + +--echo # +--echo # Function defaults run 1. No microsecond precision. +--echo # +let $current_timestamp=CURRENT_TIMESTAMP; +let $now=NOW(); +let $timestamp=TIMESTAMP; +let $datetime=DATETIME; +source 'include/function_defaults.inc'; + +--echo # +--echo # Function defaults run 2. Six digits scale on seconds precision. +--echo # +let $current_timestamp=CURRENT_TIMESTAMP(6); +let $now=NOW(6); +let $timestamp=TIMESTAMP(6); +let $datetime=DATETIME(6); +source 'include/function_defaults.inc'; diff --git a/mysql-test/t/function_defaults_notembedded.test b/mysql-test/t/function_defaults_notembedded.test new file mode 100644 index 00000000000..3d686c4b272 --- /dev/null +++ b/mysql-test/t/function_defaults_notembedded.test @@ -0,0 +1,18 @@ +--echo # +--echo # Test of function defaults for non-embedded server. +--echo # + +--source include/not_embedded.inc +--source include/have_debug_sync.inc + +--echo # +--echo # Function defaults run 1. No microsecond precision. +--echo # +let $timestamp=TIMESTAMP; +--source include/function_defaults_notembedded.inc + +--echo # +--echo # Function defaults run 2. Six digits scale on seconds precision. +--echo # +let $timestamp=TIMESTAMP(6); +--source include/function_defaults_notembedded.inc diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 575c30431b6..1c17743e7f1 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -86,17 +86,16 @@ drop table t1; # Test for TIMESTAMP column with default now() and on update now() clauses # -# These statements should fail. ---error 1293 create table t1 (t1 timestamp, t2 timestamp default now()); ---error 1293 +drop table t1; create table t1 (t1 timestamp, t2 timestamp on update now()); ---error 1293 +drop table t1; create table t1 (t1 timestamp, t2 timestamp default now() on update now()); ---error 1293 +drop table t1; create table t1 (t1 timestamp default now(), t2 timestamp on update now()); ---error 1293 +drop table t1; create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now()); +drop table t1; # Let us test TIMESTAMP auto-update behaviour # Also we will test behaviour of TIMESTAMP field in SHOW CREATE TABLE and diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 21e3634f6c7..fb0887e25d1 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -829,9 +829,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, (int) table->field[ET_FIELD_ON_COMPLETION]->val_int())) goto end; - /* Don't update create on row update. */ - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - /* mysql_event_fill_row() calls my_error() in case of error so no need to handle it here @@ -1133,8 +1130,6 @@ update_timing_fields_for_event(THD *thd, goto end; store_record(table, record[1]); - /* Don't update create on row update. */ - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; my_tz_OFFSET0->gmt_sec_to_TIME(&time, last_executed); fields[ET_FIELD_LAST_EXECUTED]->set_notnull(); diff --git a/sql/field.cc b/sql/field.cc index a3d3d951887..9a54dbf6c49 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4419,10 +4419,12 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, { /* For 4.0 MYD and 4.0 InnoDB compatibility */ flags|= UNSIGNED_FLAG | BINARY_FLAG; - if (unireg_check != NONE && !share->timestamp_field) + if (unireg_check != NONE) { - /* This timestamp has auto-update */ - share->timestamp_field= this; + /* + This TIMESTAMP column is hereby quietly assumed to have an insert or + update default function. + */ flags|= TIMESTAMP_FLAG; if (unireg_check != TIMESTAMP_DN_FIELD) flags|= ON_UPDATE_NOW_FLAG; @@ -4430,40 +4432,6 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, } -/** - Get auto-set type for TIMESTAMP field. - - Returns value indicating during which operations this TIMESTAMP field - should be auto-set to current timestamp. -*/ -timestamp_auto_set_type Field_timestamp::get_auto_set_type() const -{ - switch (unireg_check) - { - case TIMESTAMP_DN_FIELD: - return TIMESTAMP_AUTO_SET_ON_INSERT; - case TIMESTAMP_UN_FIELD: - return TIMESTAMP_AUTO_SET_ON_UPDATE; - case TIMESTAMP_OLD_FIELD: - /* - Although we can have several such columns in legacy tables this - function should be called only for first of them (i.e. the one - having auto-set property). - */ - DBUG_ASSERT(table->timestamp_field == this); - /* Fall-through */ - case TIMESTAMP_DNUN_FIELD: - return TIMESTAMP_AUTO_SET_ON_BOTH; - default: - /* - Normally this function should not be called for TIMESTAMPs without - auto-set property. - */ - DBUG_ASSERT(0); - return TIMESTAMP_NO_AUTO_SET; - } -} - my_time_t Field_timestamp::get_timestamp(ulong *sec_part) const { ASSERT_COLUMN_MARKED_FOR_READ; @@ -4713,6 +4681,16 @@ int Field_timestamp::set_time() return 0; } +void Field_timestamp::set_explicit_default(Item *value) +{ + if (value && + ((value->type() == Item::DEFAULT_VALUE_ITEM && + !((Item_default_value*)value)->arg) || + (!maybe_null() && value->is_null()))) + return; + flags|= HAS_EXPLICIT_DEFAULT; +} + void Field_timestamp_hires::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); @@ -5836,6 +5814,20 @@ void Field_datetime::sql_type(String &res) const res.set_ascii(STRING_WITH_LEN("datetime")); } + +int Field_datetime::set_time() +{ + THD *thd= current_thd; + MYSQL_TIME now_time; + thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start()); + now_time.second_part= thd->query_start_sec_part(); + set_notnull(); + store_TIME(&now_time); + thd->time_zone_used= 1; + return 0; +} + + void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime) { ulonglong packed= sec_part_shift(pack_time(ltime), dec); @@ -8857,16 +8849,37 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, { uint sign_len, allowed_type_modifier= 0; ulong max_field_charlength= MAX_FIELD_CHARLENGTH; + const bool on_update_is_function= + (fld_on_update_value != NULL && + fld_on_update_value->type() == Item::FUNC_ITEM); DBUG_ENTER("Create_field::init()"); field= 0; field_name= fld_name; - def= fld_default_value; flags= fld_type_modifier; option_list= create_opt; - unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ? - Field::NEXT_NUMBER : Field::NONE); + + if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM) + { + /* We have a function default for insertions. */ + def= NULL; + unireg_check= on_update_is_function ? + Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates. + Field::TIMESTAMP_DN_FIELD; // only for insertions. + } + else + { + /* No function default for insertions. Either NULL or a constant. */ + def= fld_default_value; + if (on_update_is_function) + unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates + else + unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG) != 0 ? + Field::NEXT_NUMBER : // Automatic increment. + Field::NONE; + } + decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0; if (decimals >= NOT_FIXED_DEC) { @@ -9089,44 +9102,6 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, } length+= MAX_DATETIME_WIDTH + (length ? 1 : 0); flags|= UNSIGNED_FLAG; - - if (fld_default_value) - { - /* Grammar allows only NOW() value for ON UPDATE clause */ - if (fld_default_value->type() == Item::FUNC_ITEM && - ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC) - { - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD: - Field::TIMESTAMP_DN_FIELD); - /* - We don't need default value any longer moreover it is dangerous. - Everything handled by unireg_check further. - */ - def= 0; - } - else - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD: - Field::NONE); - } - else - { - /* - If we have default TIMESTAMP NOT NULL column without explicit DEFAULT - or ON UPDATE values then for the sake of compatiblity we should treat - this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't - have another TIMESTAMP column with auto-set option before this one) - or DEFAULT 0 (in other cases). - So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will - replace this value by TIMESTAMP_DNUN_FIELD or NONE later when - information about all TIMESTAMP fields in table will be availiable. - - If we have TIMESTAMP NULL column without explicit DEFAULT value - we treat it as having DEFAULT NULL attribute. - */ - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD : - (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD : - Field::NONE)); - } break; case MYSQL_TYPE_DATE: /* We don't support creation of MYSQL_TYPE_DATE anymore */ @@ -9592,11 +9567,18 @@ Create_field::Create_field(Field *old_field,Field *orig_field) def=0; char_length= length; - if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && - old_field->ptr && orig_field && - (sql_type != MYSQL_TYPE_TIMESTAMP || /* set def only if */ - old_field->table->timestamp_field != old_field || /* timestamp field */ - unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */ + /* + Copy the default value from the column object orig_field, if: + 1) The column has a constant default value. + 2) The column type is not a BLOB type. + 3) The original column (old_field) was properly initialized with a record + buffer pointer. + 4) The original column doesn't have a default function to auto-initialize + the column on INSERT + */ + if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && // 1) 2) + old_field->ptr && orig_field && // 3) + !old_field->has_insert_default_function()) // 4) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff), charset); @@ -9780,3 +9762,12 @@ key_map Field::get_possible_keys() return (table->pos_in_table_list->is_materialized_derived() ? part_of_key : key_start); } + + +void Field::set_explicit_default(Item *value) +{ + if (value && value->type() == Item::DEFAULT_VALUE_ITEM && + !((Item_default_value*)value)->arg) + return; + flags|= HAS_EXPLICIT_DEFAULT; +} diff --git a/sql/field.h b/sql/field.h index f22bab0409d..7006e0bfbe8 100644 --- a/sql/field.h +++ b/sql/field.h @@ -329,6 +329,37 @@ public: *null_ptr= ((*null_ptr & (uchar) ~null_bit) | (null_ptr[l_offset] & null_bit)); } + + bool has_insert_default_function() const + { + return unireg_check == TIMESTAMP_DN_FIELD || + unireg_check == TIMESTAMP_DNUN_FIELD; + } + + bool has_update_default_function() const + { + return unireg_check == TIMESTAMP_UN_FIELD || + unireg_check == TIMESTAMP_DNUN_FIELD; + } + + virtual void set_explicit_default(Item *value); + + /** + Evaluates the @c INSERT default function and stores the result in the + field. If no such function exists for the column, or the function is not + valid for the column's data type, invoking this function has no effect. + */ + virtual int evaluate_insert_default_function() { return 0; } + + + /** + Evaluates the @c UPDATE default function, if one exists, and stores the + result in the record buffer. If no such function exists for the column, + or the function is not valid for the column's data type, invoking this + function has no effect. + */ + virtual int evaluate_update_default_function() { return 0; } + virtual bool binary() const { return 1; } virtual bool zero_pack() const { return 1; } virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } @@ -1239,12 +1270,26 @@ public: virtual int set_time(); virtual void set_default() { - if (table->timestamp_field == this && - unireg_check != TIMESTAMP_UN_FIELD) + if (has_insert_default_function()) set_time(); else Field::set_default(); } + virtual void set_explicit_default(Item *value); + virtual int evaluate_insert_default_function() + { + int res= 0; + if (has_insert_default_function()) + res= set_time(); + return res; + } + virtual int evaluate_update_default_function() + { + int res= 0; + if (has_update_default_function()) + res= set_time(); + return res; + } /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */ virtual my_time_t get_timestamp(ulong *sec_part) const; virtual void store_TIME(my_time_t timestamp, ulong sec_part) @@ -1252,7 +1297,6 @@ public: int4store(ptr,timestamp); } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - timestamp_auto_set_type get_auto_set_type() const; uchar *pack(uchar *to, const uchar *from, uint max_length __attribute__((unused))) { @@ -1503,6 +1547,28 @@ public: void sql_type(String &str) const; bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + virtual int set_time(); + virtual void set_default() + { + if (has_insert_default_function()) + set_time(); + else + Field::set_default(); + } + virtual int evaluate_insert_default_function() + { + int res= 0; + if (has_insert_default_function()) + res= set_time(); + return res; + } + virtual int evaluate_update_default_function() + { + int res= 0; + if (has_update_default_function()) + res= set_time(); + return res; + } uchar *pack(uchar* to, const uchar *from, uint max_length __attribute__((unused))) { diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 2878f25ed14..6ba4fe46441 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2906,8 +2906,6 @@ int ha_ndbcluster::write_row(uchar *record) } ha_statistic_increment(&SSV::ha_write_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); if (!(op= trans->getNdbOperation(m_table))) ERR_RETURN(trans->getNdbError()); @@ -3146,11 +3144,6 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) } ha_statistic_increment(&SSV::ha_update_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - { - table->timestamp_field->set_time(); - bitmap_set_bit(table->write_set, table->timestamp_field->field_index); - } if (m_use_partition_function && (error= get_parts_for_update(old_data, new_data, table->record[0], diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b3f97d35033..5f58247a79d 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3451,8 +3451,8 @@ void ha_partition::try_semi_consistent_read(bool yes) ADDITIONAL INFO: - We have to set timestamp fields and auto_increment fields, because those - may be used in determining which partition the row should be written to. + We have to set auto_increment fields, because those may be used in + determining which partition the row should be written to. */ int ha_partition::write_row(uchar * buf) @@ -3463,7 +3463,6 @@ int ha_partition::write_row(uchar * buf) bool have_auto_increment= table->next_number_field && buf == table->record[0]; my_bitmap_map *old_map; THD *thd= ha_thd(); - timestamp_auto_set_type saved_timestamp_type= table->timestamp_field_type; ulonglong saved_sql_mode= thd->variables.sql_mode; bool saved_auto_inc_field_not_null= table->auto_increment_field_not_null; #ifdef NOT_NEEDED @@ -3472,11 +3471,6 @@ int ha_partition::write_row(uchar * buf) DBUG_ENTER("ha_partition::write_row"); DBUG_ASSERT(buf == m_rec0); - /* If we have a timestamp column, update it to the current time */ - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - /* If we have an auto_increment column and we are writing a changed row or a new row, then update the auto_increment value in the record. @@ -3552,7 +3546,6 @@ int ha_partition::write_row(uchar * buf) exit: thd->variables.sql_mode= saved_sql_mode; table->auto_increment_field_not_null= saved_auto_inc_field_not_null; - table->timestamp_field_type= saved_timestamp_type; DBUG_RETURN(error); } @@ -3587,18 +3580,8 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data) uint32 new_part_id, old_part_id; int error= 0; longlong func_value; - timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type; DBUG_ENTER("ha_partition::update_row"); - /* - We need to set timestamp field once before we calculate - the partition. Then we disable timestamp calculations - inside m_file[*]->update_row() methods - */ - if (orig_timestamp_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - if ((error= get_parts_for_update(old_data, new_data, table->record[0], m_part_info, &old_part_id, &new_part_id, &func_value))) @@ -3672,7 +3655,6 @@ exit: info(HA_STATUS_AUTO); set_auto_increment_if_higher(table->found_next_number_field); } - table->timestamp_field_type= orig_timestamp_type; DBUG_RETURN(error); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 132f778ee08..bc787db95da 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9885,23 +9885,6 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability */ } - /* - We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill - any TIMESTAMP column with data from the row but instead will use - the event's current time. - As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra - columns, we know that all TIMESTAMP columns on slave will receive explicit - data from the row, so TIMESTAMP_NO_AUTO_SET is ok. - When we allow a table without TIMESTAMP to be replicated to a table having - more columns including a TIMESTAMP column, or when we allow a TIMESTAMP - column to be replicated into a BIGINT column and the slave's table has a - TIMESTAMP column, then the slave's TIMESTAMP column will take its value - from set_time() which we called earlier (consistent with SBR). And then in - some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to - analyze if explicit data is provided for slave's TIMESTAMP columns). - */ - m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - /* Honor next number column if present */ m_table->next_number_field= m_table->found_next_number_field; /* @@ -10984,8 +10967,6 @@ Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability if ((err= find_key())) return err; - m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - return 0; } diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index d7c66af769a..bd837adc9d9 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -924,22 +924,6 @@ int Write_rows_log_event_old::do_before_row_operations(TABLE *table) from the start. */ table->file->ha_start_bulk_insert(0); - /* - We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill - any TIMESTAMP column with data from the row but instead will use - the event's current time. - As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra - columns, we know that all TIMESTAMP columns on slave will receive explicit - data from the row, so TIMESTAMP_NO_AUTO_SET is ok. - When we allow a table without TIMESTAMP to be replicated to a table having - more columns including a TIMESTAMP column, or when we allow a TIMESTAMP - column to be replicated into a BIGINT column and the slave's table has a - TIMESTAMP column, then the slave's TIMESTAMP column will take its value - from set_time() which we called earlier (consistent with SBR). And then in - some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to - analyze if explicit data is provided for slave's TIMESTAMP columns). - */ - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; return error; } @@ -1128,8 +1112,6 @@ int Update_rows_log_event_old::do_before_row_operations(TABLE *table) if (!m_memory) return HA_ERR_OUT_OF_MEM; - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - return error; } @@ -2589,22 +2571,6 @@ Write_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabil from the start. */ m_table->file->ha_start_bulk_insert(0); - /* - We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill - any TIMESTAMP column with data from the row but instead will use - the event's current time. - As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra - columns, we know that all TIMESTAMP columns on slave will receive explicit - data from the row, so TIMESTAMP_NO_AUTO_SET is ok. - When we allow a table without TIMESTAMP to be replicated to a table having - more columns including a TIMESTAMP column, or when we allow a TIMESTAMP - column to be replicated into a BIGINT column and the slave's table has a - TIMESTAMP column, then the slave's TIMESTAMP column will take its value - from set_time() which we called earlier (consistent with SBR). And then in - some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to - analyze if explicit data is provided for slave's TIMESTAMP columns). - */ - m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; return error; } @@ -2814,8 +2780,6 @@ Update_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabi return HA_ERR_OUT_OF_MEM; } - m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - return 0; } diff --git a/sql/sp.cc b/sql/sp.cc index a1ff4db375b..0d9bbb37ede 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1350,7 +1350,6 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name, } store_record(table,record[1]); - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); if (chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f3ba0073c69..11f962dd414 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2426,7 +2426,6 @@ sp_head::fill_field_definition(THD *thd, LEX *lex, { LEX_STRING cmt = { 0, 0 }; uint unused1= 0; - int unused2= 0; if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec, lex->type, (Item*) 0, (Item*) 0, &cmt, 0, @@ -2443,8 +2442,7 @@ sp_head::fill_field_definition(THD *thd, LEX *lex, sp_prepare_create_field(thd, field_def); - if (prepare_create_field(field_def, &unused1, &unused2, &unused2, - HA_CAN_GEOMETRY)) + if (prepare_create_field(field_def, &unused1, HA_CAN_GEOMETRY)) { return TRUE; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 85e9227c154..fd587640503 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8800,13 +8800,13 @@ err_no_arena: */ static bool -fill_record(THD * thd, List<Item> &fields, List<Item> &values, +fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, bool ignore_errors) { List_iterator_fast<Item> f(fields),v(values); Item *value, *fld; Item_field *field; - TABLE *table= 0, *vcol_table= 0; + TABLE *vcol_table= 0; bool save_abort_on_warning= thd->abort_on_warning; bool save_no_errors= thd->no_errors; DBUG_ENTER("fill_record"); @@ -8828,12 +8828,13 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name); goto err; } - table= field->field->table; - table->auto_increment_field_not_null= FALSE; + DBUG_ASSERT(field->field->table == table_arg); + table_arg->auto_increment_field_not_null= FALSE; f.rewind(); } else if (thd->lex->unit.insert_table_with_stored_vcol) vcol_table= thd->lex->unit.insert_table_with_stored_vcol; + while ((fld= f++)) { if (!(field= fld->filed_for_view_update())) @@ -8843,7 +8844,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, } value=v++; Field *rfield= field->field; - table= rfield->table; + TABLE* table= rfield->table; if (rfield == table->next_number_field) table->auto_increment_field_not_null= TRUE; if (rfield->vcol_info && @@ -8861,6 +8862,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0)); goto err; } + rfield->set_explicit_default(value); DBUG_ASSERT(vcol_table == 0 || vcol_table == table); vcol_table= table; } @@ -8875,8 +8877,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, err: thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; - if (table) - table->auto_increment_field_not_null= FALSE; + if (fields.elements) + table_arg->auto_increment_field_not_null= FALSE; DBUG_RETURN(TRUE); } @@ -8905,13 +8907,13 @@ err: */ bool -fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, +fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields, List<Item> &values, bool ignore_errors, - Table_triggers_list *triggers, enum trg_event_type event) { bool result; - result= (fill_record(thd, fields, values, ignore_errors) || + Table_triggers_list *triggers= table->triggers; + result= (fill_record(thd, table, fields, values, ignore_errors) || (triggers && triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE))); /* @@ -8920,7 +8922,6 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, */ if (!result && triggers) { - TABLE *table= 0; List_iterator_fast<Item> f(fields); Item *fld; Item_field *item_field; @@ -8928,9 +8929,7 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, { fld= (Item_field*)f++; item_field= fld->filed_for_view_update(); - if (item_field && item_field->field && - (table= item_field->field->table) && - table->vfield) + if (item_field && item_field->field && table && table->vfield) result= update_virtual_fields(thd, table, TRUE); } } @@ -8960,13 +8959,12 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, */ bool -fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors, - bool use_value) +fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, + bool ignore_errors, bool use_value) { List_iterator_fast<Item> v(values); List<TABLE> tbl_list; Item *value; - TABLE *table= 0; Field *field; bool abort_on_warning_saved= thd->abort_on_warning; DBUG_ENTER("fill_record"); @@ -8981,7 +8979,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors, On INSERT or UPDATE fields are checked to be from the same table, thus we safely can take table from the first field. */ - table= (*ptr)->table; + DBUG_ASSERT((*ptr)->table == table); /* Reset the table->auto_increment_field_not_null as it is valid for @@ -9012,6 +9010,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors, else if (value->save_in_field(field, 0) < 0) goto err; + field->set_explicit_default(value); } /* Update virtual fields*/ thd->abort_on_warning= FALSE; @@ -9051,13 +9050,13 @@ err: */ bool -fill_record_n_invoke_before_triggers(THD *thd, Field **ptr, +fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr, List<Item> &values, bool ignore_errors, - Table_triggers_list *triggers, enum trg_event_type event) { bool result; - result= (fill_record(thd, ptr, values, ignore_errors, FALSE) || + Table_triggers_list *triggers= table->triggers; + result= (fill_record(thd, table, ptr, values, ignore_errors, FALSE) || (triggers && triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE))); /* @@ -9066,7 +9065,6 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr, */ if (!result && triggers && *ptr) { - TABLE *table= (*ptr)->table; if (table->vfield) result= update_virtual_fields(thd, table, TRUE); } @@ -9706,11 +9704,6 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup) /* Make sure all columns get assigned to a default value */ table->use_all_columns(); table->no_replicate= 1; - /* - Don't set automatic timestamps as we may want to use time of logging, - not from query start - */ - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; } else thd->restore_backup_open_tables_state(backup); diff --git a/sql/sql_base.h b/sql/sql_base.h index 3deb97c9730..fbe905375bb 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -170,15 +170,15 @@ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); TABLE *find_temporary_table(THD *thd, const char *table_key, uint table_key_length); void close_thread_tables(THD *thd); -bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields, +bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, + List<Item> &fields, List<Item> &values, bool ignore_errors, - Table_triggers_list *triggers, enum trg_event_type event); -bool fill_record_n_invoke_before_triggers(THD *thd, Field **field, +bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, + Field **field, List<Item> &values, bool ignore_errors, - Table_triggers_list *triggers, enum trg_event_type event); bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, @@ -191,7 +191,7 @@ bool setup_fields(THD *thd, Item** ref_pointer_array, List<Item> &item, enum_mark_columns mark_used_columns, List<Item> *sum_func_list, bool allow_sum_func); void unfix_fields(List<Item> &items); -bool fill_record(THD *thd, Field **field, List<Item> &values, +bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values, bool ignore_errors, bool use_value); Field * @@ -304,6 +304,7 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, void mark_tmp_table_for_reuse(TABLE *table); bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE); +int update_default_fields(TABLE *table); int dynamic_column_error_message(enum_dyncol_func_result rc); extern TABLE *unused_tables; diff --git a/sql/sql_class.h b/sql/sql_class.h index 3aa0c5ae9c7..b1153edbac8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4120,6 +4120,16 @@ public: */ #define CF_FORCE_ORIGINAL_BINLOG_FORMAT (1U << 10) +/** + Statement that inserts new rows (INSERT, REPLACE, LOAD) +*/ +#define CF_INSERTS_DATA (1U << 11) + +/** + Statement that updates existing rows (UPDATE, multi-update) +*/ +#define CF_UPDATES_DATA (1U << 12) + /* Bits in server_command_flags */ /** diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index e65ec3c22b0..1193c7c27f4 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -257,7 +257,7 @@ my_bool Expression_cache_tmptable::put_value(Item *value) } *(items.head_ref())= value; - fill_record(table_thd, cache_table->field, items, TRUE, TRUE); + fill_record(table_thd, cache_table, cache_table->field, items, TRUE, TRUE); if (table_thd->is_error()) goto err;; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3c3b9f85727..5d95ac2716d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -191,11 +191,6 @@ error: different table maps, like on select ... insert map Store here table map for used fields - NOTE - Clears TIMESTAMP_AUTO_SET_ON_INSERT from table->timestamp_field_type - or leaves it as is, depending on if timestamp should be updated or - not. - RETURN 0 OK -1 Error @@ -234,8 +229,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (check_grant_all_columns(thd, INSERT_ACL, &field_it)) return -1; #endif - clear_timestamp_auto_bits(table->timestamp_field_type, - TIMESTAMP_AUTO_SET_ON_INSERT); /* No fields are provided so all fields must be provided in the values. Thus we set all bits in the write set. @@ -295,18 +288,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dup_field->field_name); return -1; } - if (table->timestamp_field) // Don't automaticly set timestamp if used - { - if (bitmap_is_set(table->write_set, - table->timestamp_field->field_index)) - clear_timestamp_auto_bits(table->timestamp_field_type, - TIMESTAMP_AUTO_SET_ON_INSERT); - else - { - bitmap_set_bit(table->write_set, - table->timestamp_field->field_index); - } - } + if (table->default_field) + table->mark_default_fields_for_write(); } /* Mark virtual columns used in the insert statement */ if (table->vfield) @@ -339,9 +322,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, update_fields The update fields. NOTE - If the update fields include the timestamp field, - remove TIMESTAMP_AUTO_SET_ON_UPDATE from table->timestamp_field_type. - If the update fields include an autoinc field, set the table->next_number_field_updated flag. @@ -355,21 +335,9 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, List<Item> &update_values, table_map *map) { TABLE *table= insert_table_list->table; - my_bool timestamp_mark; my_bool autoinc_mark; - LINT_INIT(timestamp_mark); LINT_INIT(autoinc_mark); - if (table->timestamp_field) - { - /* - Unmark the timestamp field so that we can check if this is modified - by update_fields - */ - timestamp_mark= bitmap_test_and_clear(table->write_set, - table->timestamp_field->field_index); - } - table->next_number_field_updated= FALSE; if (table->found_next_number_field) @@ -393,17 +361,8 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, insert_table_list, map, false)) return -1; - if (table->timestamp_field) - { - /* Don't set timestamp column if this is modified. */ - if (bitmap_is_set(table->write_set, - table->timestamp_field->field_index)) - clear_timestamp_auto_bits(table->timestamp_field_type, - TIMESTAMP_AUTO_SET_ON_UPDATE); - if (timestamp_mark) - bitmap_set_bit(table->write_set, - table->timestamp_field->field_index); - } + if (table->default_field) + table->mark_default_fields_for_write(); if (table->found_next_number_field) { @@ -709,7 +668,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, int error, res; bool transactional_table, joins_freed= FALSE; bool changed; - bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); + const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); bool using_bulk_insert= 0; uint value_count; ulong counter = 1; @@ -913,8 +872,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (fields.elements || !value_count) { restore_record(table,s->default_values); // Get empty record - if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0, - table->triggers, + if (fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0, TRG_EVENT_INSERT)) { if (values_list.elements != 1 && ! thd->is_error()) @@ -958,8 +916,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, share->default_values[share->null_bytes - 1]; } } - if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0, - table->triggers, + if (fill_record_n_invoke_before_triggers(thd, table, table->field, *values, 0, TRG_EVENT_INSERT)) { if (values_list.elements != 1 && ! thd->is_error()) @@ -971,6 +928,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } + if (table->default_field && table->update_default_fields()) + { + error= 1; + break; + } if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? @@ -987,7 +949,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (lock_type == TL_WRITE_DELAYED) { LEX_STRING const st_query = { query, thd->query_length() }; + DEBUG_SYNC(thd, "before_write_delayed"); error=write_delayed(thd, table, duplic, st_query, ignore, log_on); + DEBUG_SYNC(thd, "after_write_delayed"); query=0; } else @@ -1696,13 +1660,32 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) restore_record(table,record[1]); DBUG_ASSERT(info->update_fields->elements == info->update_values->elements); - if (fill_record_n_invoke_before_triggers(thd, *info->update_fields, + if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields, *info->update_values, info->ignore, - table->triggers, TRG_EVENT_UPDATE)) goto before_trg_err; + bool different_records= (!records_are_comparable(table) || + compare_record(table)); + /* + Default fields must be updated before checking view updateability. + This branch of INSERT is executed only when a UNIQUE key was violated + with the ON DUPLICATE KEY UPDATE option. In this case the INSERT + operation is transformed to an UPDATE, and the default fields must + be updated as this is an UPDATE. + */ + if (different_records && table->default_field) + { + bool res; + enum_sql_command cmd= thd->lex->sql_command; + thd->lex->sql_command= SQLCOM_UPDATE; + res= table->update_default_fields(); + thd->lex->sql_command= cmd; + if (res) + goto err; + } + /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ if (info->view && (res= info->view->view_check_option(current_thd, info->ignore)) == @@ -1713,7 +1696,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->file->restore_auto_increment(prev_insert_id); info->touched++; - if (!records_are_comparable(table) || compare_record(table)) + if (different_records) { if ((error=table->file->ha_update_row(table->record[1], table->record[0])) && @@ -1784,8 +1767,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) */ if (last_uniq_key(table,key_nr) && !table->file->referenced_by_foreign_key() && - (table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET || - table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) && (!table->triggers || !table->triggers->has_delete_triggers())) { if ((error=table->file->ha_update_row(table->record[1], @@ -1948,7 +1929,6 @@ public: ulonglong forced_insert_id; ulong auto_increment_increment; ulong auto_increment_offset; - timestamp_auto_set_type timestamp_field_type; LEX_STRING query; Time_zone *time_zone; @@ -2321,7 +2301,7 @@ end_create: TABLE *Delayed_insert::get_local_table(THD* client_thd) { my_ptrdiff_t adjust_ptrs; - Field **field,**org_field, *found_next_number_field; + Field **field,**org_field, *found_next_number_field, **dfield_ptr; TABLE *copy; TABLE_SHARE *share; uchar *bitmap; @@ -2390,6 +2370,12 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) bitmap= (uchar*) (field + share->fields + 1); copy->record[0]= (bitmap + share->column_bitmap_size*3); memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength); + if (share->default_fields) + { + copy->default_field= (Field**) client_thd->alloc((share->default_fields+1)* + sizeof(Field**)); + dfield_ptr= copy->default_field; + } /* Make a copy of all fields. The copied fields need to point into the copied record. This is done @@ -2407,18 +2393,19 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) (*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0] if (*org_field == found_next_number_field) (*field)->table->found_next_number_field= *field; + if (share->default_fields && + ((*org_field)->has_insert_default_function() || + (*org_field)->has_update_default_function())) + { + /* Put the newly copied field into the set of default fields. */ + *dfield_ptr= *field; + (*dfield_ptr)->unireg_check= (*org_field)->unireg_check; + dfield_ptr++; + } } *field=0; - - /* Adjust timestamp */ - if (table->timestamp_field) - { - /* Restore offset as this may have been reset in handle_inserts */ - copy->timestamp_field= - (Field_timestamp*) copy->field[share->timestamp_field_offset]; - copy->timestamp_field->unireg_check= table->timestamp_field->unireg_check; - copy->timestamp_field_type= copy->timestamp_field->get_auto_set_type(); - } + if (share->default_fields) + *dfield_ptr= NULL; /* Adjust in_use for pointing to client thread */ copy->in_use= client_thd; @@ -2508,7 +2495,6 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt; row->first_successful_insert_id_in_prev_stmt= thd->first_successful_insert_id_in_prev_stmt; - row->timestamp_field_type= table->timestamp_field_type; /* Add session variable timezone Time_zone object will not be freed even the thread is ended. @@ -3051,7 +3037,6 @@ bool Delayed_insert::handle_inserts(void) row->first_successful_insert_id_in_prev_stmt; thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt= row->stmt_depends_on_first_successful_insert_id_in_prev_stmt; - table->timestamp_field_type= row->timestamp_field_type; table->auto_increment_field_not_null= row->auto_increment_field_not_null; /* Copy the session variables. */ @@ -3527,6 +3512,8 @@ int select_insert::send_data(List<Item> &values) thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields store_values(values); + if (table->default_field && table->update_default_fields()) + DBUG_RETURN(1); thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; if (thd->is_error()) { @@ -3586,11 +3573,11 @@ int select_insert::send_data(List<Item> &values) void select_insert::store_values(List<Item> &values) { if (fields->elements) - fill_record_n_invoke_before_triggers(thd, *fields, values, 1, - table->triggers, TRG_EVENT_INSERT); + fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1, + TRG_EVENT_INSERT); else - fill_record_n_invoke_before_triggers(thd, table->field, values, 1, - table->triggers, TRG_EVENT_INSERT); + fill_record_n_invoke_before_triggers(thd, table, table->field, values, 1, + TRG_EVENT_INSERT); } void select_insert::send_error(uint errcode,const char *err) @@ -3808,7 +3795,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, DBUG_ENTER("create_table_from_items"); tmp_table.alias= 0; - tmp_table.timestamp_field= 0; tmp_table.s= &share; init_tmp_table_share(thd, &share, "", 0, "", ""); @@ -3817,6 +3803,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, tmp_table.null_row= 0; tmp_table.maybe_null= 0; + promote_first_timestamp_column(&alter_info->create_list); + while ((item=it++)) { Create_field *cr_field; @@ -4056,8 +4044,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) for (Field **f= field ; *f ; f++) bitmap_set_bit(table->write_set, (*f)->field_index); - /* Don't set timestamp if used */ - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; table->next_number_field=table->found_next_number_field; restore_record(table,s->default_values); // Get empty record @@ -4133,8 +4119,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) void select_create::store_values(List<Item> &values) { - fill_record_n_invoke_before_triggers(thd, field, values, 1, - table->triggers, TRG_EVENT_INSERT); + fill_record_n_invoke_before_triggers(thd, table, field, values, 1, + TRG_EVENT_INSERT); } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 98031c96225..18cea96dd92 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -273,7 +273,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, for (field=table->field; *field ; field++) fields_vars.push_back(new Item_field(*field)); bitmap_set_all(table->write_set); - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; /* Let us also prepare SET clause, altough it is probably empty in this case. @@ -289,21 +288,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); - /* - Check whenever TIMESTAMP field with auto-set feature specified - explicitly. - */ - if (table->timestamp_field) - { - if (bitmap_is_set(table->write_set, - table->timestamp_field->field_index)) - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - else - { - bitmap_set_bit(table->write_set, - table->timestamp_field->field_index); - } - } + /* Add all fields with default functions to table->write_set. */ + if (table->default_field) + table->mark_default_fields_for_write(); /* Fix the expressions in SET clause */ if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0)) DBUG_RETURN(TRUE); @@ -850,7 +837,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER(ER_WARN_TOO_FEW_RECORDS), thd->warning_info->current_row_for_warning()); if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP) - ((Field_timestamp*) field)->set_time(); + field->set_time(); } else { @@ -864,6 +851,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, pos[length]=save_chr; if ((pos+=length) > read_info.row_end) pos= read_info.row_end; /* Fills rest with space */ + field->set_explicit_default(NULL); } } if (pos != read_info.row_end) @@ -876,10 +864,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } if (thd->killed || - fill_record_n_invoke_before_triggers(thd, set_fields, set_values, + fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values, ignore_check_option_errors, - table->triggers, - TRG_EVENT_INSERT)) + TRG_EVENT_INSERT) || + (table->default_field && table->update_default_fields())) DBUG_RETURN(1); switch (table_list->view_check_option(thd, @@ -994,10 +982,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(1); } field->set_null(); + field->set_explicit_default(NULL); if (!field->maybe_null()) { if (field->type() == MYSQL_TYPE_TIMESTAMP) - ((Field_timestamp*) field)->set_time(); + field->set_time(); else if (field != table->next_number_field) field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1); @@ -1025,6 +1014,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (field == table->next_number_field) table->auto_increment_field_not_null= TRUE; field->store((char*) pos, length, read_info.read_charset); + field->set_explicit_default(NULL); } else if (item->type() == Item::STRING_ITEM) { @@ -1066,7 +1056,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(1); } if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP) - ((Field_timestamp*) field)->set_time(); + field->set_time(); /* TODO: We probably should not throw warning for each field. But how about intention to always have the same number @@ -1093,10 +1083,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } if (thd->killed || - fill_record_n_invoke_before_triggers(thd, set_fields, set_values, + fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values, ignore_check_option_errors, - table->triggers, - TRG_EVENT_INSERT)) + TRG_EVENT_INSERT) || + (table->default_field && table->update_default_fields())) DBUG_RETURN(1); switch (table_list->view_check_option(thd, @@ -1206,7 +1196,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (!field->maybe_null()) { if (field->type() == FIELD_TYPE_TIMESTAMP) - ((Field_timestamp *) field)->set_time(); + field->set_time(); else if (field != table->next_number_field) field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1); @@ -1225,6 +1215,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (field == table->next_number_field) table->auto_increment_field_not_null= TRUE; field->store((char *) tag->value.ptr(), tag->value.length(), cs); + field->set_explicit_default(NULL); } else ((Item_user_var_as_out_param *) item)->set_value( @@ -1269,10 +1260,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } if (thd->killed || - fill_record_n_invoke_before_triggers(thd, set_fields, set_values, + fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values, ignore_check_option_errors, - table->triggers, - TRG_EVENT_INSERT)) + TRG_EVENT_INSERT) || + (table->default_field && table->update_default_fields())) DBUG_RETURN(1); switch (table_list->view_check_option(thd, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 175c2c1d672..aa62e450f9d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -268,12 +268,14 @@ void init_update_queries(void) CF_CAN_GENERATE_ROW_EVENTS; sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | - CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS ; + CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS | + CF_INSERTS_DATA; sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS; + CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS | + CF_INSERTS_DATA; sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS; @@ -290,21 +292,21 @@ void init_update_queries(void) sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_UPDATES_DATA; sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_UPDATES_DATA; sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA; sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA; sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS; sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS; sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA; sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA; sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS; sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS; @@ -5881,11 +5883,11 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, no need fix_fields() We allow only one function as part of default value - - NOW() as default for TIMESTAMP type. + NOW() as default for TIMESTAMP and DATETIME type. */ if (default_value->type() == Item::FUNC_ITEM && !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC && - type == MYSQL_TYPE_TIMESTAMP)) + (type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME))) { my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str); DBUG_RETURN(1); @@ -5907,7 +5909,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, } } - if (on_update_value && type != MYSQL_TYPE_TIMESTAMP) + if (on_update_value && + !(type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME)) { my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str); DBUG_RETURN(1); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 2bec12e4f66..f042f028450 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6526,9 +6526,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->pack_frm_data= NULL; lpt->pack_frm_len= 0; - /* Never update timestamp columns when alter */ - lpt->table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - if (table->file->alter_table_flags(alter_info->flags) & HA_PARTITION_ONE_PHASE) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f0c786dea86..e89d4c14c96 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9463,7 +9463,7 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) if (item->is_null()) DBUG_RETURN(NESTED_LOOP_OK); } - fill_record(thd, table->field, sjm->sjm_table_cols, TRUE, FALSE); + fill_record(thd, table, table->field, sjm->sjm_table_cols, TRUE, FALSE); if (thd->is_error()) DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ if ((error= table->file->ha_write_tmp_row(table->record[0]))) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8a106b8ec6f..a71ca73789f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1108,8 +1108,35 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, #define LIST_PROCESS_HOST_LEN 64 -static bool get_field_default_value(THD *thd, Field *timestamp_field, - Field *field, String *def_value, + +/** + Print "ON UPDATE" clause of a field into a string. + + @param timestamp_field Pointer to timestamp field of a table. + @param field The field to generate ON UPDATE clause for. + @bool lcase Whether to print in lower case. + @return false on success, true on error. +*/ +static bool print_on_update_clause(Field *field, String *val, bool lcase) +{ + DBUG_ASSERT(val->charset()->mbminlen == 1); + val->length(0); + if (field->has_update_default_function()) + { + if (lcase) + val->append(STRING_WITH_LEN("on update ")); + else + val->append(STRING_WITH_LEN("ON UPDATE ")); + val->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); + if (field->decimals() > 0) + val->append_parenthesized(field->decimals()); + return true; + } + return false; +} + + +static bool get_field_default_value(THD *thd, Field *field, String *def_value, bool quoted) { bool has_default; @@ -1120,8 +1147,7 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field, We are using CURRENT_TIMESTAMP instead of NOW because it is more standard */ - has_now_default= (timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_UN_FIELD); + has_now_default= field->has_insert_default_function(); has_default= (field_type != FIELD_TYPE_BLOB && !(field->flags & NO_DEFAULT_VALUE_FLAG) && @@ -1133,7 +1159,11 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field, if (has_default) { if (has_now_default) + { def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); + if (field->decimals() > 0) + def_value->append_parenthesized(field->decimals()); + } else if (!field->is_null()) { // Not null by default char tmp[MAX_FIELD_WIDTH]; @@ -1365,16 +1395,18 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, } if (!field->vcol_info && - get_field_default_value(thd, table->timestamp_field, - field, &def_value, 1)) + get_field_default_value(thd, field, &def_value, 1)) { packet->append(STRING_WITH_LEN(" DEFAULT ")); packet->append(def_value.ptr(), def_value.length(), system_charset_info); } - if (!limited_mysql_mode && table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_DN_FIELD) - packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP")); + if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false)) + { + packet->append(STRING_WITH_LEN(" ")); + packet->append(def_value); + } + if (field->unireg_check == Field::NEXT_NUMBER && !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS)) @@ -4758,7 +4790,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, const char *wild= lex->wild ? lex->wild->ptr() : NullS; CHARSET_INFO *cs= system_charset_info; TABLE *show_table; - Field **ptr, *field, *timestamp_field; + Field **ptr, *field; int count; DBUG_ENTER("get_schema_column_record"); @@ -4782,7 +4814,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, show_table= tables->table; count= 0; ptr= show_table->field; - timestamp_field= show_table->timestamp_field; show_table->use_all_columns(); // Required for default restore_record(show_table, s->default_values); @@ -4830,7 +4861,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, cs); table->field[4]->store((longlong) count, TRUE); - if (get_field_default_value(thd, timestamp_field, field, &type, 0)) + if (get_field_default_value(thd, field, &type, 0)) { table->field[5]->store(type.ptr(), type.length(), cs); table->field[5]->set_notnull(); @@ -4847,10 +4878,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, if (field->unireg_check == Field::NEXT_NUMBER) table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs); - if (timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_DN_FIELD) - table->field[17]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"), - cs); + if (print_on_update_clause(field, &type, true)) + table->field[17]->store(type.ptr(), type.length(), cs); if (field->vcol_info) { if (field->stored_in_db) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 75029a03790..89536b93feb 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -502,6 +502,24 @@ bool String::append(IO_CACHE* file, uint32 arg_length) return FALSE; } + +/** + Append a parenthesized number to String. + Used in various pieces of SHOW related code. + + @param nr Number + @param radix Radix, optional parameter, 10 by default. +*/ +bool String::append_parenthesized(long nr, int radix) +{ + char buff[64], *end; + buff[0]= '('; + end= int10_to_str(nr, buff + 1, radix); + *end++ = ')'; + return append(buff, (uint) (end - buff)); +} + + bool String::append_with_prefill(const char *s,uint32 arg_length, uint32 full_length, char fill_char) { diff --git a/sql/sql_string.h b/sql/sql_string.h index 2f0cd9103dc..633170a5e20 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -343,6 +343,7 @@ public: bool append(IO_CACHE* file, uint32 arg_length); bool append_with_prefill(const char *s, uint32 arg_length, uint32 full_length, char fill_char); + bool append_parenthesized(long nr, int radix= 10); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5a6090e5d9a..e66d4f529de 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2607,7 +2607,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, prepare_create_field() sql_field field to prepare for packing blob_columns count for BLOBs - timestamps count for timestamps table_flags table flags DESCRIPTION @@ -2621,7 +2620,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, int prepare_create_field(Create_field *sql_field, uint *blob_columns, - int *timestamps, int *timestamps_with_niladic, longlong table_flags) { unsigned int dup_val_count; @@ -2743,21 +2741,6 @@ int prepare_create_field(Create_field *sql_field, (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); break; case MYSQL_TYPE_TIMESTAMP: - /* We should replace old TIMESTAMP fields with their newer analogs */ - if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) - { - if (!*timestamps) - { - sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; - (*timestamps_with_niladic)++; - } - else - sql_field->unireg_check= Field::NONE; - } - else if (sql_field->unireg_check != Field::NONE) - (*timestamps_with_niladic)++; - - (*timestamps)++; /* fall-through */ default: sql_field->pack_flag=(FIELDFLAG_NUMBER | @@ -2829,6 +2812,40 @@ bool check_duplicate_warning(THD *thd, char *msg, ulong length) } +/** + Modifies the first column definition whose SQL type is TIMESTAMP + by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. + + @param column_definitions The list of column definitions, in the physical + order in which they appear in the table. + */ +void promote_first_timestamp_column(List<Create_field> *column_definitions) +{ + List_iterator<Create_field> it(*column_definitions); + Create_field *column_definition; + + while ((column_definition= it++) != NULL) + { + if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP || // TIMESTAMP + column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy + { + if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL, + column_definition->def == NULL && // no constant default, + column_definition->unireg_check == Field::NONE) // no function default + { + DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to " + "DEFAULT CURRENT_TIMESTAMP ON UPDATE " + "CURRENT_TIMESTAMP", + column_definition->field_name + )); + column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD; + } + return; + } + } +} + + /* Preparation for table creation @@ -2869,7 +2886,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ulong record_offset= 0; KEY *key_info; KEY_PART_INFO *key_part_info; - int timestamps= 0, timestamps_with_niladic= 0; int field_no,dup_no; int select_field_pos,auto_increment=0; List_iterator<Create_field> it(alter_info->create_list); @@ -3153,7 +3169,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_ASSERT(sql_field->charset != 0); if (prepare_create_field(sql_field, &blob_columns, - ×tamps, ×tamps_with_niladic, file->ha_table_flags())) DBUG_RETURN(TRUE); if (sql_field->sql_type == MYSQL_TYPE_VARCHAR) @@ -3184,12 +3199,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, record_offset+= sql_field->pack_length; } } - if (timestamps_with_niladic > 1) - { - my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS, - ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0)); - DBUG_RETURN(TRUE); - } if (auto_increment > 1) { my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0)); @@ -4558,6 +4567,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, /* Got lock. */ DEBUG_SYNC(thd, "locked_table_name"); + promote_first_timestamp_column(&alter_info->create_list); + result= mysql_create_table_no_lock(thd, create_table->db, create_table->table_name, create_info, alter_info, FALSE, 0, &is_trans); @@ -6371,6 +6382,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, need_copy_table= alter_info->change_level; set_table_default_charset(thd, create_info, db); + promote_first_timestamp_column(&alter_info->create_list); if (thd->variables.old_alter_table || (table->s->db_type() != create_info->db_type) @@ -6668,6 +6680,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock"); DBUG_EXECUTE_IF("sleep_before_create_table_no_lock", my_sleep(100000);); + /* Create a table with a temporary name. With create_info->frm_only == 1 this creates a .frm file only. @@ -6738,8 +6751,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, */ if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER)) { - /* We don't want update TIMESTAMP fields during ALTER TABLE. */ - new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; DBUG_EXECUTE_IF("abort_copy_table", { my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); @@ -7316,6 +7327,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, ulonglong prev_insert_id, time_to_report_progress; List_iterator<Create_field> it(create); Create_field *def; + Field **dfield_ptr= to->default_field; DBUG_ENTER("copy_data_between_tables"); /* Two or 3 stages; Sorting, copying data and update indexes */ @@ -7345,6 +7357,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, errpos= 3; copy_end=copy; + to->s->default_fields= 0; for (Field **ptr=to->field ; *ptr ; ptr++) { def=it++; @@ -7364,8 +7377,23 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, } (copy_end++)->set(*ptr,def->field,0); } - + else + { + /* + Update the set of auto-update fields to contain only the newly added + fields. Only these fields should be updated automatically. Old fields + keep their current values, and therefore should not be present in the + set of autoupdate fields. + */ + if ((*ptr)->has_insert_default_function()) + { + *(dfield_ptr++)= *ptr; + ++to->s->default_fields; + } + } } + if (dfield_ptr) + *dfield_ptr= NULL; if (order) { @@ -7456,6 +7484,11 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, prev_insert_id= to->file->next_insert_id; if (to->vfield) update_virtual_fields(thd, to, TRUE); + if (to->default_field && to->update_default_fields()) + { + error= 1; + break; + } if (thd->is_error()) { error= 1; diff --git a/sql/sql_table.h b/sql/sql_table.h index 00de6ed1b8d..9d5e768a5a3 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -187,7 +187,6 @@ void close_cached_table(THD *thd, TABLE *table); void sp_prepare_create_field(THD *thd, Create_field *sql_field); int prepare_create_field(Create_field *sql_field, uint *blob_columns, - int *timestamps, int *timestamps_with_niladic, longlong table_flags); CHARSET_INFO* get_sql_field_charset(Create_field *sql_field, HA_CREATE_INFO *create_info); @@ -208,6 +207,9 @@ void execute_ddl_log_recovery(); bool execute_ddl_log_entry(THD *thd, uint first_entry); bool check_duplicate_warning(THD *thd, char *msg, ulong length); +template<typename T> class List; +void promote_first_timestamp_column(List<Create_field> *column_definitions); + /* These prototypes where under INNODB_COMPATIBILITY_HOOKS. */ diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8dcae907926..e6c9d7e4977 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -63,7 +63,7 @@ int select_union::send_data(List<Item> &values) return 0; if (table->no_rows_with_nulls) table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT; - fill_record(thd, table->field, values, TRUE, FALSE); + fill_record(thd, table, table->field, values, TRUE, FALSE); if (thd->is_error()) return 1; if (table->no_rows_with_nulls) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index fb0951410a4..4f31da92107 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -342,19 +342,8 @@ int mysql_update(THD *thd, my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); DBUG_RETURN(1); } - if (table->timestamp_field) - { - // Don't set timestamp column if this is modified - if (bitmap_is_set(table->write_set, - table->timestamp_field->field_index)) - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; - else - { - if (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE) - bitmap_set_bit(table->write_set, - table->timestamp_field->field_index); - } - } + if (table->default_field) + table->mark_default_fields_for_write(); #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ @@ -389,7 +378,7 @@ int mysql_update(THD *thd, to compare records and detect data change. */ if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) && - (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE)) + table->default_field && table->has_default_function(true)) bitmap_union(table->read_set, table->write_set); // Don't count on usage of 'only index' when calculating which key to use table->covering_keys.clear_all(); @@ -686,8 +675,7 @@ int mysql_update(THD *thd, continue; /* repeat the read of the same row if it still exists */ store_record(table,record[1]); - if (fill_record_n_invoke_before_triggers(thd, fields, values, 0, - table->triggers, + if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0, TRG_EVENT_UPDATE)) break; /* purecov: inspected */ @@ -695,6 +683,11 @@ int mysql_update(THD *thd, if (!can_compare_record || compare_record(table)) { + if (table->default_field && table->update_default_fields()) + { + error= 1; + break; + } if ((res= table_list->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { @@ -1241,11 +1234,6 @@ int mysql_multi_update_prepare(THD *thd) while ((tl= ti++)) { TABLE *table= tl->table; - /* Only set timestamp column if this is not modified */ - if (table->timestamp_field && - bitmap_is_set(table->write_set, - table->timestamp_field->field_index)) - table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; /* if table will be updated then check that it is unique */ if (table->map & tables_for_update) @@ -1495,8 +1483,7 @@ int multi_update::prepare(List<Item> ¬_used_values, to compare records and detect data change. */ if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) && - (((uint) table->timestamp_field_type) & - TIMESTAMP_AUTO_SET_ON_UPDATE)) + table->default_field && table->has_default_function(true)) bitmap_union(table->read_set, table->write_set); } } @@ -1875,10 +1862,10 @@ int multi_update::send_data(List<Item> ¬_used_values) table->status|= STATUS_UPDATED; store_record(table,record[1]); - if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset], + if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset], *values_for_table[offset], 0, - table->triggers, - TRG_EVENT_UPDATE)) + TRG_EVENT_UPDATE) || + (table->default_field && table->update_default_fields())) DBUG_RETURN(1); /* @@ -1979,7 +1966,7 @@ int multi_update::send_data(List<Item> ¬_used_values) } while ((tbl= tbl_it++)); /* Store regular updated fields in the row. */ - fill_record(thd, + fill_record(thd, tmp_table, tmp_table->field + 1 + unupdated_check_opt_tables.elements, *values_for_table[offset], TRUE, FALSE); @@ -2169,7 +2156,10 @@ int multi_update::do_updates() for (copy_field_ptr=copy_field; copy_field_ptr != copy_field_end; copy_field_ptr++) + { (*copy_field_ptr->do_copy)(copy_field_ptr); + copy_field_ptr->to_field->set_explicit_default(NULL); + } if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, @@ -2179,6 +2169,8 @@ int multi_update::do_updates() if (!can_compare_record || compare_record(table)) { int error; + if (table->default_field && (error= table->update_default_fields())) + goto err2; if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 555efaf366d..16bfa16d0a9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5873,9 +5873,9 @@ attribute: NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; } | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; } | DEFAULT now_or_signed_literal { Lex->default_value=$2; } - | ON UPDATE_SYM NOW_SYM optional_braces + | ON UPDATE_SYM NOW_SYM opt_time_precision { - Item *item= new (YYTHD->mem_root) Item_func_now_local(6); + Item *item= new (YYTHD->mem_root) Item_func_now_local($4); if (item == NULL) MYSQL_YYABORT; Lex->on_update_value= item; @@ -5967,9 +5967,9 @@ type_with_opt_collate: now_or_signed_literal: - NOW_SYM optional_braces + NOW_SYM opt_time_precision { - $$= new (YYTHD->mem_root) Item_func_now_local(6); + $$= new (YYTHD->mem_root) Item_func_now_local($2); if ($$ == NULL) MYSQL_YYABORT; } diff --git a/sql/table.cc b/sql/table.cc index 47b2cae1a04..cdf11116266 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1250,6 +1250,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, com_length= uint2korr(forminfo+284); vcol_screen_length= uint2korr(forminfo+286); share->vfields= 0; + share->default_fields= 0; share->stored_fields= share->fields; if (forminfo[46] != (uchar)255) { @@ -1581,8 +1582,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (reg_field->unireg_check == Field::NEXT_NUMBER) share->found_next_number_field= field_ptr; - if (share->timestamp_field == reg_field) - share->timestamp_field_offset= i; if (use_hash) { @@ -1604,6 +1603,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (share->stored_rec_length>=recpos) share->stored_rec_length= recpos-1; } + if (reg_field->has_insert_default_function() || + reg_field->has_update_default_function()) + ++share->default_fields; } *field_ptr=0; // End marker /* Sanity checks: */ @@ -2315,7 +2317,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, uint records, i, bitmap_size; bool error_reported= FALSE; uchar *record, *bitmaps; - Field **field_ptr, **vfield_ptr; + Field **field_ptr, **vfield_ptr, **dfield_ptr; uint8 save_context_analysis_only= thd->lex->context_analysis_only; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, @@ -2419,9 +2421,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, if (share->found_next_number_field) outparam->found_next_number_field= outparam->field[(uint) (share->found_next_number_field - share->field)]; - if (share->timestamp_field) - outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset]; - /* Fix key->name and key_part->field */ if (share->key_parts) @@ -2472,7 +2471,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, } /* - Process virtual columns, if any. + Process virtual and default columns, if any. */ if (!share->vfields) outparam->vfield= NULL; @@ -2484,10 +2483,26 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, goto err; outparam->vfield= vfield_ptr; + } + + if (!share->default_fields) + outparam->default_field= NULL; + else + { + if (!(dfield_ptr = (Field **) alloc_root(&outparam->mem_root, + (uint) ((share->default_fields+1)* + sizeof(Field*))))) + goto err; + outparam->default_field= dfield_ptr; + } + + if (share->vfields || share->default_fields) + { + /* Reuse the same loop both for virtual and default fields. */ for (field_ptr= outparam->field; *field_ptr; field_ptr++) { - if ((*field_ptr)->vcol_info) + if (share->vfields && (*field_ptr)->vcol_info) { if (unpack_vcol_info_from_frm(thd, outparam, @@ -2500,8 +2515,15 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, } *(vfield_ptr++)= *field_ptr; } + if (share->default_fields && + ((*field_ptr)->has_insert_default_function() || + (*field_ptr)->has_update_default_function())) + *(dfield_ptr++)= *field_ptr; } - *vfield_ptr= 0; // End marker + if (share->vfields) + *vfield_ptr= 0; // End marker + if (share->default_fields) + *dfield_ptr= 0; // End marker } #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -3924,9 +3946,6 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) DBUG_ASSERT(!auto_increment_field_not_null); auto_increment_field_not_null= FALSE; - if (timestamp_field) - timestamp_field_type= timestamp_field->get_auto_set_type(); - pos_in_table_list= tl; clear_column_bitmaps(); @@ -5843,6 +5862,48 @@ void TABLE::mark_virtual_columns_for_write(bool insert_fl) /** +*/ + +bool TABLE::has_default_function(bool is_update) +{ + Field **dfield_ptr, *dfield; + bool res= false; + for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++) + { + dfield= (*dfield_ptr); + if (is_update) + res= dfield->has_update_default_function(); + else + res= dfield->has_insert_default_function(); + if (res) + return res; + } + return res; +} + + +/** +*/ + +void TABLE::mark_default_fields_for_write() +{ + Field **dfield_ptr, *dfield; + enum_sql_command cmd= in_use->lex->sql_command; + for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++) + { + dfield= (*dfield_ptr); + if (((cmd == SQLCOM_INSERT || cmd == SQLCOM_INSERT_SELECT || + cmd == SQLCOM_REPLACE || cmd == SQLCOM_REPLACE_SELECT || + cmd == SQLCOM_LOAD) && + dfield->has_insert_default_function()) || + ((cmd == SQLCOM_UPDATE || cmd == SQLCOM_UPDATE_MULTI) && + dfield->has_update_default_function())) + bitmap_set_bit(write_set, dfield->field_index); + } +} + + +/** @brief Allocate space for keys @@ -6448,6 +6509,50 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write) DBUG_RETURN(0); } + +/** + Update all DEFAULT and/or ON INSERT fields. + + @details + + @retval + 0 Success + @retval + >0 Error occurred when storing a virtual field value +*/ + +int TABLE::update_default_fields() +{ + DBUG_ENTER("update_default_fields"); + Field **dfield_ptr, *dfield; + int res= 0; + enum_sql_command cmd= in_use->lex->sql_command; + + DBUG_ASSERT(default_field); + /* Iterate over virtual fields in the table */ + for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++) + { + dfield= (*dfield_ptr); + /* + If an explicit default value for a filed overrides the default, + do not update the field with its automatic default value. + */ + if (!(dfield->flags & HAS_EXPLICIT_DEFAULT)) + { + if (sql_command_flags[cmd] & CF_INSERTS_DATA) + res= dfield->evaluate_insert_default_function(); + if (sql_command_flags[cmd] & CF_UPDATES_DATA) + res= dfield->evaluate_update_default_function(); + if (res) + DBUG_RETURN(res); + } + /* Unset the explicit default flag for the next record. */ + dfield->flags&= ~HAS_EXPLICIT_DEFAULT; + } + DBUG_RETURN(res); +} + + /* @brief Reset const_table flag diff --git a/sql/table.h b/sql/table.h index 9e26f907920..e98f93c8bb1 100644 --- a/sql/table.h +++ b/sql/table.h @@ -350,25 +350,6 @@ public: }; -/* - Values in this enum are used to indicate how a tables TIMESTAMP field - should be treated. It can be set to the current timestamp on insert or - update or both. - WARNING: The values are used for bit operations. If you change the - enum, you must keep the bitwise relation of the values. For example: - (int) TIMESTAMP_AUTO_SET_ON_BOTH must be equal to - (int) TIMESTAMP_AUTO_SET_ON_INSERT | (int) TIMESTAMP_AUTO_SET_ON_UPDATE. - We use an enum here so that the debugger can display the value names. -*/ -enum timestamp_auto_set_type -{ - TIMESTAMP_NO_AUTO_SET= 0, TIMESTAMP_AUTO_SET_ON_INSERT= 1, - TIMESTAMP_AUTO_SET_ON_UPDATE= 2, TIMESTAMP_AUTO_SET_ON_BOTH= 3 -}; -#define clear_timestamp_auto_bits(_target_, _bits_) \ - (_target_)= (enum timestamp_auto_set_type)((int)(_target_) & ~(int)(_bits_)) - -class Field_timestamp; class Field_blob; class Table_triggers_list; @@ -608,7 +589,6 @@ struct TABLE_SHARE /* The following is copied to each TABLE on OPEN */ Field **field; Field **found_next_number_field; - Field *timestamp_field; /* Used only during open */ KEY *key_info; /* data of keys in database */ uint *blob_field; /* Index to blobs in Field arrray*/ @@ -680,7 +660,6 @@ struct TABLE_SHARE uint uniques; /* Number of UNIQUE index */ uint null_fields; /* number of null fields */ uint blob_fields; /* number of blob fields */ - uint timestamp_field_offset; /* Field number for timestamp field */ uint varchar_fields; /* number of varchar fields */ uint db_create_options; /* Create options from database */ uint db_options_in_use; /* Options in use */ @@ -695,6 +674,7 @@ struct TABLE_SHARE uint column_bitmap_size; uchar frm_version; uint vfields; /* Number of computed (virtual) fields */ + uint default_fields; /* Number of default fields in */ bool use_ext_keys; /* Extended keys can be used */ bool null_field_first; bool system; /* Set if system table (one record) */ @@ -1007,8 +987,9 @@ public: Field *next_number_field; /* Set if next_number is activated */ Field *found_next_number_field; /* Set on open */ - Field_timestamp *timestamp_field; Field **vfield; /* Pointer to virtual fields*/ + /* Fields that are updated automatically on INSERT or UPDATE. */ + Field **default_field; /* Table's triggers, 0 if there are no of them */ Table_triggers_list *triggers; @@ -1064,19 +1045,6 @@ public: */ ha_rows quick_condition_rows; - /* - If this table has TIMESTAMP field with auto-set property (pointed by - timestamp_field member) then this variable indicates during which - operations (insert only/on update/in both cases) we should set this - field to current timestamp. If there are no such field in this table - or we should not automatically set its value during execution of current - statement then the variable contains TIMESTAMP_NO_AUTO_SET (i.e. 0). - - Value of this variable is set for each statement in open_table() and - if needed cleared later in statement processing code (see mysql_update() - as example). - */ - timestamp_auto_set_type timestamp_field_type; table_map map; /* ID bit of table (1,2,4,8,16...) */ uint lock_position; /* Position in MYSQL_LOCK.table */ @@ -1207,6 +1175,8 @@ public: void mark_columns_needed_for_insert(void); bool mark_virtual_col(Field *field); void mark_virtual_columns_for_write(bool insert_fl); + void mark_default_fields_for_write(); + bool has_default_function(bool is_update); inline void column_bitmaps_set(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg) { @@ -1293,6 +1263,7 @@ public: bool update_const_key_parts(COND *conds); uint actual_n_key_parts(KEY *keyinfo); ulong actual_key_flags(KEY *keyinfo); + int update_default_fields(); }; diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index b21e0561322..396d5a21be5 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -905,8 +905,6 @@ int ha_archive::write_row(uchar *buf) DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); ha_statistic_increment(&SSV::ha_write_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); mysql_mutex_lock(&share->mutex); if (!share->archive_write_open) diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index d31e5ee8d89..ba731298d02 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -999,9 +999,6 @@ int ha_tina::write_row(uchar * buf) ha_statistic_increment(&SSV::ha_write_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - size= encode_quote(buf); if (!share->tina_write_opened) @@ -1064,9 +1061,6 @@ int ha_tina::update_row(const uchar * old_data, uchar * new_data) ha_statistic_increment(&SSV::ha_update_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - size= encode_quote(new_data); /* diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 549001ab08b..18ba636c0e2 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1849,8 +1849,6 @@ int ha_federated::write_row(uchar *buf) values_string.length(0); insert_field_value_string.length(0); ha_statistic_increment(&SSV::ha_write_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); /* start both our field and field values strings diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index a10285a81aa..7f095a9b96e 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1993,8 +1993,6 @@ int ha_federatedx::write_row(uchar *buf) values_string.length(0); insert_field_value_string.length(0); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); /* start both our field and field values strings diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index 305a8cae720..b9eef0d155b 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -241,8 +241,6 @@ void ha_heap::update_key_stats() int ha_heap::write_row(uchar * buf) { int res; - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) { if ((res= update_auto_increment())) @@ -264,8 +262,6 @@ int ha_heap::write_row(uchar * buf) int ha_heap::update_row(const uchar * old_data, uchar * new_data) { int res; - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); res= heap_update(file,old_data,new_data); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c7adc9a7671..62694df0422 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5163,9 +5163,6 @@ ha_innobase::write_row( ha_statistic_increment(&SSV::ha_write_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - sql_command = thd_sql_command(user_thd); if ((sql_command == SQLCOM_ALTER_TABLE @@ -5573,9 +5570,6 @@ ha_innobase::update_row( ha_statistic_increment(&SSV::ha_update_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - if (prebuilt->upd_node) { uvect = prebuilt->upd_node->update; } else { diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 785fe5d8226..f8f3abc41a5 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1248,10 +1248,6 @@ int ha_maria::close(void) int ha_maria::write_row(uchar * buf) { - /* If we have a timestamp column, update it to the current time */ - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - /* If we have an auto_increment column and we are writing a changed row or a new row, then update the auto_increment value in the record. @@ -2245,8 +2241,6 @@ bool ha_maria::is_crashed() const int ha_maria::update_row(const uchar * old_data, uchar * new_data) { CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT"); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); return maria_update(file, old_data, new_data); } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 73e0fadd530..5f24a002014 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -832,10 +832,6 @@ int ha_myisam::close(void) int ha_myisam::write_row(uchar *buf) { - /* If we have a timestamp column, update it to the current time */ - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - /* If we have an auto_increment column and we are writing a changed row or a new row, then update the auto_increment value in the record. @@ -1656,8 +1652,6 @@ bool ha_myisam::is_crashed() const int ha_myisam::update_row(const uchar *old_data, uchar *new_data) { - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); return mi_update(file,old_data,new_data); } diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 47a3abb78d2..2c1e85ec9ff 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1078,8 +1078,6 @@ int ha_myisammrg::write_row(uchar * buf) if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables) DBUG_RETURN(HA_ERR_TABLE_READONLY); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) { int error; @@ -1093,8 +1091,6 @@ int ha_myisammrg::update_row(const uchar * old_data, uchar * new_data) { DBUG_ASSERT(this->file->children_attached); ha_statistic_increment(&SSV::ha_update_count); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); return myrg_update(file,old_data,new_data); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 97a30a81d12..004d57e6efd 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5933,9 +5933,6 @@ ha_innobase::write_row( DBUG_RETURN(HA_ERR_CRASHED); } - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - sql_command = thd_sql_command(user_thd); if ((sql_command == SQLCOM_ALTER_TABLE @@ -6359,9 +6356,6 @@ ha_innobase::update_row( DBUG_RETURN(HA_ERR_CRASHED); } - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - if (prebuilt->upd_node) { uvect = prebuilt->upd_node->update; } else { |