MySQL8 の TIMESTAMP, DATETIME におけるExplicit Default な式定義について

MySQL8.0.13 からDEFAULT値に簡単な式を書けるようになりました。超便利です。

timestampでデフォルト値を書いたときに`ALTER TABLE ADD COLUMN`や`CREATE INDEX`などテーブル加工をするとエラーになることがあります。
挙動が罠ではあるが、バグではないです。


https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html#data-type-defaults-implicit

```
The exception is that, for TIMESTAMP and DATETIME columns, you can specify the CURRENT_TIMESTAMP function as the default, without enclosing parentheses. See Section 11.2.5, “Automatic Initialization and Updating for TIMESTAMP and DATETIME”.
```

リファレンスマニュアルを見ても、TIMESTAMP と DATETIME だけは例外と書いてあります。
この2つだけは規定のデフォルト値に従わなければいけません、
詳細は、 https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html
基本は、ここに記述されてるもののみデフォルトにできます。

TIMESTAMPやDATETIMEはデフォルトを指定しないときのImplicit Default の挙動が他の型と異なるため、NOT NULLのときにトラブルになることがあります。
INSERT や UPDATEなどデータを入れるときはExplicit Defaultの式がおかしくてもエラーにならずに良い感じに補正されて動きますが、ALTERなどのときはNOT NULL型ではエラーになります。


```
mysql> create table tt1 (t timestamp not null default (CURRENT_TIMESTAMP + INTERVAL 1 YEAR), i int);
mysql> create table tt2 (t timestamp not null default CURRENT_TIMESTAMP, i int);
mysql> create table tt3 (t timestamp null default (CURRENT_TIMESTAMP + INTERVAL 1 YEAR), i int);
mysql> create table tt4 (t timestamp null default CURRENT_TIMESTAMP, i int);
```

```
mysql> desc tt1;
+-------+-----------+------+-----+---------------------------+-------------------+
| Field | Type      | Null | Key | Default                   | Extra             |
+-------+-----------+------+-----+---------------------------+-------------------+
| t     | timestamp | NO   |     | (now() + interval 1 year) | DEFAULT_GENERATED |
| i     | int       | YES  |     | NULL                      |                   |
+-------+-----------+------+-----+---------------------------+-------------------+
2 rows in set (0.00 sec)

mysql> desc tt2;
+-------+-----------+------+-----+-------------------+-------------------+
| Field | Type      | Null | Key | Default           | Extra             |
+-------+-----------+------+-----+-------------------+-------------------+
| t     | timestamp | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| i     | int       | YES  |     | NULL              |                   |
+-------+-----------+------+-----+-------------------+-------------------+
2 rows in set (0.00 sec)

mysql> desc tt3;
+-------+-----------+------+-----+---------------------------+-------------------+
| Field | Type      | Null | Key | Default                   | Extra             |
+-------+-----------+------+-----+---------------------------+-------------------+
| t     | timestamp | YES  |     | (now() + interval 1 year) | DEFAULT_GENERATED |
| i     | int       | YES  |     | NULL                      |                   |
+-------+-----------+------+-----+---------------------------+-------------------+
2 rows in set (0.00 sec)

mysql> desc tt4;
+-------+-----------+------+-----+-------------------+-------------------+
| Field | Type      | Null | Key | Default           | Extra             |
+-------+-----------+------+-----+-------------------+-------------------+
| t     | timestamp | YES  |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| i     | int       | YES  |     | NULL              |                   |
+-------+-----------+------+-----+-------------------+-------------------+
2 rows in set (0.00 sec)
```

```
mysql> insert tt1 set i=0;
mysql> insert tt2 set i=0;
mysql> insert tt3 set i=0;
mysql> insert tt4 set i=0;
```
普通に入る。

```
mysql> alter table tt1 add j int;
ERROR 1067 (42000): Invalid default value for 't'

mysql> alter table tt2 add j int;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table tt3 add j int;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table tt4 add j int;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0
```

tt1 だけALTERがエラーになります。
NULLを許可してる場合はエラーになりませんが、たまたま動いてると考えたほうが良さそうです。