マイグレーションで出力されるSQLを確認する方法

DjangoでDBに関連した操作をするとき、django-adminmakemigrationsマイグレーションファイルを作成して、migrateマイグレーションを実行します。

そのマイグレーション実行時に実行されるSQLを確認するには、sqlmigrateを利用します。

Django4.2で検証しました。

sqlmigrate

https://docs.djangoproject.com/ja/4.2/ref/django-admin/#sqlmigrate

コマンドは以下のようになっています。

django-admin sqlmigrate app_label migration_name

app_labelはアプリケーション名、 migration_nameマイグレーションファイルの名前です。

例えば、taskテーブルをrenameする次のようなマイグレーションファイル0008_alter_task_table.pyが生成されたとします。

# Generated by Django 4.2.9 on 2024-03-28 11:25

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ("tasks", "0007_taskbackup"),
    ]

    operations = [
        migrations.AlterModelTable(
            name="task",
            table="task_rename",
        ),
    ]

その時、コマンドは以下のようになります。

django-admin sqlmigrate tasks 0008_alter_task_table

実行結果(SQLite3の場合)は次のような結果が返されます。

BEGIN;
--
-- Rename table for task to task_rename
--
ALTER TABLE "task" RENAME TO "task_rename";
COMMIT;

マイグレーションファイルについて

今回の例のマイグレーションファイル 0008_alter_task_table.py で内部で AlterModelTable が利用されています。

DBスキーマ操作用のクラスが定義されており、リファレンスで言うと以下のようなページがあります。

https://docs.djangoproject.com/ja/4.2/ref/migration-operations/#altermodeltable

定義しているモデルのテーブル名を変更します(Meta サブクラスの db_table オプションを参照します)。

と記述されており、大まかなレベルではリファレンスからどういうことをするか確認できます。

詳細に確認するには、sqlmigrateを実行したら良いんだな、という理解をしています。

SQLの定義場所

そして、SQLは以下に定義されています。

https://github.com/django/django/blob/main/django/db/backends/base/schema.py#L75

ここではこの変数をベースにSQLが発行されていたことが確認できます。

sql_rename_table = "ALTER TABLE %(old_table)s RENAME TO %(new_table)s"

また、今回はSQLite3の場合でしたが、MySQL PostgreSQLで実行できないSQLもあるので、それを吸収できるよう、それぞれのDBに合わせたディレクトリとファイル(及び変数)が存在します。

DBをMySQLに置き換えると、以下のようになります。

--
-- Rename table for task to task_rename
--
RENAME TABLE `task` TO `task_rename`;

コードは以下です。

https://github.com/django/django/blob/main/django/db/backends/mysql/schema.py#L7

sql_rename_table = "RENAME TABLE %(old_table)s TO %(new_table)s"

余談

何回か取り上げたSQLを確認しよう、というシリーズの延長線上になりましたが、Django任せにせず、どういう風にDBを操作しているかを確認するのも大事だなと思いました。

Djangoマイグレーションファイルも「Djangoがよしなに生成してくれるもの」くらいの認識でいましたが、マイグレーション用のクラスがあったことや、その裏側でSQLも定義されていることを改めて認識できて、世界が広がって面白いなぁと思いました。