SQLAlchemyで作成したテーブルのautoincrementについて

# はじめに
本記事はalembicとSQLAlchemyを使用してマイグレーションを管理しているプロジェクトで新規テーブルを追加した際に発生したことをまとめた備忘録です。

# 環境
Python 3.11.5
alembic 1.13.0
SQLAlchemy 2.0.23

mysql 8.0.34

# 何があったの？
とある目的で別テーブルで管理しているIDをPKにしたテーブルを作成することになりました。
他テーブルのPKをそのままPKとして使用するためautoincrementはFalseにする必要がありました。
ユーザー登録をする際はまずusersにレコードが生成されて、その生成されたレコードのPKをそのままuser_detailsのPKにする想定。
以下は実際に発生した事象を再現したものになります。

```python:既存のテーブル
class User(Base):
    __tablename__ = 'users'

    id = Column(BIGINT, primary_key=True, autoincrement=True)
    last_name = Column(VARCHAR(16))
    first_name = Column(VARCHAR(16))
```
```
以下、マイグレーションにより実際に作成されたusersテーブル
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | bigint      | NO   | PRI | NULL    | auto_increment |
| last_name  | varchar(16) | YES  |     | NULL    |                |
| first_name | varchar(16) | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
```
```python:追加のテーブル
class UserDetail(Base):
    __tablename__ = 'user_details'

    user_id = Column(BIGINT, primary_key=True)
    height = Column(INTEGER)
    weight = Column(INTEGER)
```
```
以下、マイグレーションにより追加されたuser_detailsテーブル
+---------+--------+------+-----+---------+----------------+
| Field   | Type   | Null | Key | Default | Extra          |
+---------+--------+------+-----+---------+----------------+
| user_id | bigint | NO   | PRI | NULL    | auto_increment |
| height  | int    | YES  |     | NULL    |                |
| weight  | int    | YES  |     | NULL    |                |
+---------+--------+------+-----+---------+----------------+
```

ここであれっ？てなりました。
user_detailsの定義にはPKであるuser_idのautoincrementは何も指定していないのに勝手にautoincrementされる設定になってる...

# 対応

まずは公式ドキュメントを確認。
https://docs.sqlalchemy.org/en/20/core/metadata.html#sqlalchemy.schema.Column.params.autoincrement

以下、該当部分の引用


> The default value is the string "auto", which indicates that a single-column (i.e. non-composite) primary key that is of an INTEGER type with no other client-side or server-side default constructs indicated should receive auto increment semantics automatically. Other values include True (force this column to have auto-increment semantics for a composite primary key as well), False (this column should never have auto-increment semantics), and the string "ignore_fk" (special-case for foreign key columns, see below).

autoincrementのデフォルト値ってFalseじゃないんだ！！
autoincrementのデフォルトは'auto'でINT型(もっと言うとINT, SMALLINT, BIGINT)でかつ、複合主キーでなければ自動的にオートインクリメントされる設定になるみたいでした。

なので明示的にautoincrementをFalseにするとauto_incrementが外れました。

```python:追加のテーブル(修正版)
class UserDetail(Base):
    __tablename__ = 'user_details'

    user_id = Column(BIGINT, primary_key=True, autoincrement=False)
    height = Column(INTEGER)
    weight = Column(INTEGER)
```
```
以下、マイグレーションにより追加された修正版のuser_detailsテーブル
+---------+--------+------+-----+---------+-------+
| Field   | Type   | Null | Key | Default | Extra |
+---------+--------+------+-----+---------+-------+
| user_id | bigint | NO   | PRI | NULL    |       |
| height  | int    | YES  |     | NULL    |       |
| weight  | int    | YES  |     | NULL    |       |
+---------+--------+------+-----+---------+-------+
```

めでたしめでたし。

# 参考文献


- SQLAlchemy 2.0 Documentation
https://docs.sqlalchemy.org/en/20/index.html