【Airflow】Airflow breezeのWebUIからDelete DAGを実行するとエラーになる！

## はじめに
こんにちは。ジールの@________________-_です。

ローカルでairflow breezeを利用しておりますが、WebUIのAcitonsから`Delete DAG`を実行するとエラーとなり削除できない事象が発生しました。
今までこんなこと無かった気がするので簡単に調査してみました。

`Delete DAG`を実行すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166013/42db35ff-6445-3219-ccc5-cafb0710f3f3.png)

エラーとなり削除ができない！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166013/ed0f13b7-1d48-f7af-f766-7ace105c3a3f.png)

悲しいです。。。

## 環境

Airflow breeze：v2.3.0.dev0 
すべてデフォルト設定で利用

## 結論

tag付のDAGを削除しようとしていることが原因のようでした。

## 詳細

エラー内容を確認すると、`sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) FOREIGN KEY constraint failed`と記載があります。外部キー制約が原因で動作しないようです。

また、`[SQL: DELETE FROM dag WHERE dag.dag_id IN (?)] [parameters: ('example_external_task_sensor_parent',)]`との記載もある為、dagテーブルのカラムに対して外部キーを設定しているテーブルが原因ぽいです。
早速テーブルを探してみたところ`dag_tag`テーブルを発見しました！

以下airflow breeze内部からsqliteにて確認しました。
```sh
cd ~/airflow
sqlite3 airflow.db
```

dag_tagテーブルのdag_idカラムに外部キーが設定されているのが分かります。
```sql
--表示モードをlineにする
sqlite> .mode line;
--dag_tagテーブルのDDLを表示
sqlite> select * from sqlite_master where type='table' and name='dag_tag';
>>     type = table
>>     name = dag_tag
>> tbl_name = dag_tag
>> rootpage = 4
>>      sql = CREATE TABLE dag_tag (
>>         name VARCHAR(100) NOT NULL,
>>         dag_id VARCHAR(250) NOT NULL,
>>         PRIMARY KEY (name, dag_id),
>>         FOREIGN KEY(dag_id) REFERENCES dag (dag_id)
)

```

つまり、`dag_tag`テーブルの`dag_id`カラムが`dag`テーブルの`dag_id`カラムを参照した外部キーとなっている為、
先に`dag_tag`テーブルのレコードを削除しないと、`dag`テーブルからもレコードを削除できない状態です。

念のためsqlでも同様のエラーが発生するか試してみます。
```sql
--外部キーが有効になっているか確認
sqlite> PRAGMA foreign_keys;
>> foreign_keys = 0
--外部キーを有効にする
sqlite> PRAGMA foreign_keys=true;
sqlite> PRAGMA foreign_keys;
>> foreign_keys = 1
--dagテーブルからexample_external_task_sensor_parent DAGを削除
sqlite> delete from dag where dag_id = 'example_external_task_sensor_parent';
>> Error: FOREIGN KEY constraint failed --同様に外部キー制約エラー
```

同様のエラーが発生したので今度はdag_tagテーブルから先に削除してみます。
```sql
--dag_tagテーブルからexample_external_task_sensor_parent DAGを削除
sqlite> delete from dag_tag where dag_id = 'example_external_task_sensor_parent';
--dag_tagテーブルから削除後、dagテーブルからexample_external_task_sensor_parent DAGを削除
sqlite> delete from dag where dag_id = 'example_external_task_sensor_parent';
--エラーも発生せず削除が可能
```

問題なく削除可能でした。
WebUIでも削除されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166013/767aa21e-c226-57de-e732-ca346130caa8.png)



改めて纏めると、
- DAGを作成すると、dagテーブルにレコードが登録される。
- DAGにtagを設定すると、dag_tagテーブルにもレコードが作成される。
- dag_tagテーブルのdag_idカラムは、dagテーブルのdag_idカラムを参照する外部キーとなっている。
- 上記の関係性から、tagのあるDAGを削除するには、dag_tagテーブルから対象レコードを削除した後にdagテーブルからも削除する必要がある。
- dagテーブルの対象レコードを先に削除しようとすると、dag_tagテーブルに対象レコードが存在している為外部キー制約エラーとなる。

テーブルの関係は以下の通り。
- dagテーブル：dagが登録されているテーブル
- dag_tagテーブル：dagのtagが登録されているテーブル。dag_idカラムはdagテーブルのdag_idカラムを参照した外部キー。

## おわりに
実際のコードを読んでないので正確なことは言えませんが、
**dag_tagテーブルのレコードを削除する前にdagテーブルのレコードを削除しようとしている為** エラーになっていると推測致しました。
ちなみに、DAGからtagを外すとWEBUIからも削除可能でした（tagをもともと設定していないDAGも削除可能）。
tagを設定していてもWebUIから削除出来る方法って何かあるんですかね？？？

## おまけ  コマンド実行の場合
コマンドでDAGを削除した場合はどうなるのか試してみました。

```sh
airflow dags delete -y example_external_task_sensor_parent
```

結果としては、同じエラーになったりならなかったり。。。謎です。
成功した場合は、

```sh
Remove 2 Record(s)
```
と表示されます。
ちなみに、tagを2個に増やすと、
```sh
Remove 3 Record(s)
```
と表示されます。
dagテーブルからdag1レコードと、dag_tagテーブルからdagのtag2レコードが削除されているものと思われます。
以上！

***
株式会社ジールでは、「ITリテラシーがない」「初期費用がかけられない」「親切・丁寧な支援がほしい」「ノーコード・ローコードがよい」「運用・保守の手間をかけられない」などのお客様の声を受けて、オールインワン型データ活用プラットフォーム「ZEUSCloud」を月額利用料にてご提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
 
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/?utm_source=qiita&utm_medium=referral&utm_campaign=qiita_zeuscloud_content-area