diff --git a/mysql-test/suite/innodb/r/innodb-alter-timestamp.result b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result new file mode 100644 index 00000000000..2ab81136d1f --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 ( +`i1` INT(10) UNSIGNED NOT NULL, +`d1` TIMESTAMP NULL DEFAULT NULL +) ENGINE=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i1` int(10) unsigned NOT NULL, + `d1` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 (i1) VALUES (1), (2), (3), (4), (5); +select * from t1; +i1 d1 +1 NULL +2 NULL +3 NULL +4 NULL +5 NULL +set sql_mode = 'STRICT_ALL_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 CHANGE `d1` `d1` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL; +drop table t1; +CREATE TABLE t1 ( +`i1` INT(10) UNSIGNED NOT NULL, +`d1` TIMESTAMP NULL DEFAULT NULL +) ENGINE=innodb; +INSERT INTO t1 (i1) VALUES (1), (2), (3), (4), (5); +ALTER TABLE t1 CHANGE `d1` `d1` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; +drop table t1; +set sql_mode = ''; diff --git a/mysql-test/suite/innodb/t/innodb-alter-timestamp.test b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test new file mode 100644 index 00000000000..c0b17ee6440 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test @@ -0,0 +1,27 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 ( + `i1` INT(10) UNSIGNED NOT NULL, + `d1` TIMESTAMP NULL DEFAULT NULL +) ENGINE=innodb; + +show create table t1; + +INSERT INTO t1 (i1) VALUES (1), (2), (3), (4), (5); +select * from t1; +set sql_mode = 'STRICT_ALL_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 CHANGE `d1` `d1` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL; +drop table t1; + +CREATE TABLE t1 ( + `i1` INT(10) UNSIGNED NOT NULL, + `d1` TIMESTAMP NULL DEFAULT NULL +) ENGINE=innodb; +INSERT INTO t1 (i1) VALUES (1), (2), (3), (4), (5); +ALTER TABLE t1 CHANGE `d1` `d1` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; +drop table t1; +set sql_mode = ''; + + + + diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 3f393d9d431..63bd70e89a3 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -372,6 +372,35 @@ ha_innobase::check_if_supported_inplace_alter( } } + /* If we have column that has changed from NULL -> NOT NULL + and column default has changed we need to do additional + check. */ + if ((ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE) && + (ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_DEFAULT)) { + Alter_info *alter_info = ha_alter_info->alter_info; + List_iterator def_it(alter_info->create_list); + Create_field *def; + while ((def=def_it++)) { + + /* If this is first column definition whose SQL type + is TIMESTAMP and it is defined as NOT NULL and + it has either constant default or function default + we must use "Copy" method. */ + if (is_timestamp_type(def->sql_type)) { + if ((def->flags & NOT_NULL_FLAG) != 0 && // NOT NULL + (def->def != NULL || // constant default ? + def->unireg_check != Field::NONE)) { // function default + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL); + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + break; + } + } + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true; diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index cc18f709043..e6e4f13a73e 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -372,6 +372,35 @@ ha_innobase::check_if_supported_inplace_alter( } } + /* If we have column that has changed from NULL -> NOT NULL + and column default has changed we need to do additional + check. */ + if ((ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE) && + (ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_DEFAULT)) { + Alter_info *alter_info = ha_alter_info->alter_info; + List_iterator def_it(alter_info->create_list); + Create_field *def; + while ((def=def_it++)) { + + /* If this is first column definition whose SQL type + is TIMESTAMP and it is defined as NOT NULL and + it has either constant default or function default + we must use "Copy" method. */ + if (is_timestamp_type(def->sql_type)) { + if ((def->flags & NOT_NULL_FLAG) != 0 && // NOT NULL + (def->def != NULL || // constant default ? + def->unireg_check != Field::NONE)) { // function default + ha_alter_info->unsupported_reason = innobase_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL); + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + break; + } + } + } + /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE). */ bool online = true;