# 機能設計書 9-DELETE文処理

## 概要

本ドキュメントは、SQLiteにおけるDELETE文によるデータ削除処理について、その設計と実装の詳細を記述する。テーブルからのレコード削除、インデックスエントリの削除、外部キー制約の処理について解説する。

### 本機能の処理概要

**業務上の目的・背景**：DELETE文はデータベースから不要なレコードを削除するための基本的なDML操作である。条件に基づく選択的な削除から、全行の一括削除（TRUNCATE相当）まで、データ管理の様々な要件に対応する必要がある。

**機能の利用シーン**：
- 不要データの削除
- 条件に基づく選択的削除
- 全行の一括削除
- カスケード削除（外部キー制約）
- RETURNING句を使用した削除データの取得
- WASMデモでのデータ削除処理

**主要な処理内容**：
1. DELETE文のパースとターゲットテーブルの特定
2. WHERE句による削除対象行の絞り込み
3. ビューの場合のINSTEAD OFトリガー処理
4. 読み取り専用テーブルのチェック
5. 外部キー制約のチェック（参照される側）
6. インデックスエントリの削除
7. B-Treeからの行削除
8. トリガーの実行
9. RETURNING句の処理

**関連システム・外部連携**：
- パーサー（parse.y、tokenize.c）
- WHERE句最適化（where.c）
- VDBEコードジェネレータ
- B-Treeストレージエンジン（btree.c）
- 外部キー制約処理（fkey.c）

**権限による制御**：sqlite3_set_authorizer()で設定されたauthorizerコールバックによるDELETE操作の許可/拒否が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | SQLite3 Fiddle | 主画面 | データ削除SQLの実行 |

## 機能種別

データ削除処理（CRUD操作のDelete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| テーブル名 | SrcList* | Yes | 削除対象テーブル | 存在するテーブル |
| WHERE句 | Expr* | No | 削除対象行の条件 | 省略時は全行削除 |
| ORDER BY | ExprList* | No | 削除順序 | LIMIT指定時のみ |
| LIMIT | Expr* | No | 削除件数制限 | 省略可 |
| RETURNING | ExprList* | No | 返却するカラム | 省略可 |

### 入力データソース

- 削除対象テーブルの既存データ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 影響行数 | int | 削除された行数 |
| RETURNING結果 | sqlite3_stmt* | RETURNING句指定時の結果セット |

### 出力先

- データベーステーブル（行の削除）
- インデックス（エントリの削除）
- RETURNING句指定時はアプリケーションへ

## 処理フロー

### 処理シーケンス

```
1. DELETE文のパース
   └─ ターゲットテーブルの特定

2. テーブル検索
   └─ sqlite3SrcListLookup()でテーブル情報を取得

3. 読み取り専用チェック
   └─ sqlite3IsReadOnly()で書き込み可能か確認

4. ビュー処理
   └─ sqlite3MaterializeView()でビューを一時テーブル化

5. WHERE句の最適化
   ├─ LIMIT/ORDER BY有り：sqlite3LimitWhere()
   └─ 通常：直接sqlite3WhereBegin()

6. 削除対象行のスキャン
   └─ インデックスまたはフルスキャン

7. 各行の処理
   ├─ 外部キー制約チェック（参照される側）
   ├─ BEFORE DELETEトリガー
   ├─ インデックスエントリの削除
   └─ B-Tree行の削除

8. トリガー実行
   └─ AFTER DELETEトリガー

9. RETURNING処理
   └─ 指定カラムの値を返却

10. 変更行数報告
    └─ sqlite3CodeChangeCount()
```

### フローチャート

```mermaid
flowchart TD
    A[DELETE文入力] --> B[テーブル検索]
    B --> C{読み取り専用?}
    C -->|Yes| D[エラー返却]
    C -->|No| E{ビュー?}
    E -->|Yes| F[ビュー実体化]
    E -->|No| G[WHERE句最適化]
    F --> G
    G --> H[対象行スキャン]
    H --> I[外部キーチェック]
    I --> J{違反?}
    J -->|Yes| K[カスケードまたはエラー]
    J -->|No| L[BEFORE DELETEトリガー]
    K --> L
    L --> M[インデックス削除]
    M --> N[B-Tree行削除]
    N --> O[AFTER DELETEトリガー]
    O --> P{次の行?}
    P -->|Yes| H
    P -->|No| Q{RETURNING?}
    Q -->|Yes| R[結果返却]
    Q -->|No| S[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 全行削除警告 | WHERE句なしは全行が削除対象 | WHERE省略時 |
| BR-002 | ビューの削除 | ビューへのDELETEはINSTEAD OFトリガーが必要 | ビュー対象時 |
| BR-003 | 読み取り専用テーブル | システムテーブル等は削除不可 | 読み取り専用時 |
| BR-004 | カスケード削除 | ON DELETE CASCADE設定時は参照行も削除 | FOREIGN KEY有効時 |
| BR-005 | SET NULL | ON DELETE SET NULL設定時は参照カラムをNULLに | FOREIGN KEY有効時 |
| BR-006 | RESTRICT/NO ACTION | 参照されている行は削除不可 | FOREIGN KEY有効時（デフォルト） |

### 計算ロジック

特に計算ロジックは存在しない。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| DELETE | 指定テーブル | DELETE | レコードの削除 |
| DELETE | インデックス | DELETE | インデックスエントリの削除 |
| DELETE | 参照テーブル | DELETE/UPDATE | CASCADEによる連鎖処理 |

### テーブル別操作詳細

#### 指定テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | （行全体） | WHERE条件に一致する行 | 全カラム削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_CONSTRAINT_FOREIGNKEY | 外部キー違反 | 参照されている行の削除 | 参照行を先に削除 |
| SQLITE_READONLY | 読み取り専用 | 読み取り専用接続での削除 | 書き込み可能接続を使用 |
| SQLITE_BUSY | ロック競合 | 他接続が行をロック中 | リトライまたはタイムアウト設定 |
| SQLITE_ERROR | ビュー削除エラー | INSTEAD OFトリガーなしでビュー削除 | トリガーを作成 |

### リトライ仕様

- SQLITE_BUSYは設定されたビジーハンドラに従ってリトライ
- 外部キー違反は参照関係の解消後に再試行

## トランザクション仕様

- DELETE文は暗黙のトランザクション内で実行
- 明示的トランザクション内では複数DELETEを一括コミット可能
- CASCADE処理も同一トランザクション内で実行

## パフォーマンス要件

- インデックス使用時の行特定はO(log n)
- フルスキャン時はO(n)
- インデックスエントリ削除のオーバーヘッドあり
- TRUNCATE相当（WHERE句なし）は最適化される場合あり

## セキュリティ考慮事項

- authorizerコールバックによるDELETE許可制御
- シャドウテーブルの削除制限（defensive mode）
- トリガー内でのセキュリティ考慮

## 備考

- TRUNCATE TABLE構文はSQLiteでは未サポート（DELETE FROM tableで代替）
- WHERE句なしの全行削除は最適化される
- RETURNING句でDELETE対象の行データを取得可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、DELETE処理で使用される構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | Table構造体、SrcList構造体 |
| 1-2 | delete.c | `src/delete.c` | 処理で使用する構造体と定数 |

**読解のコツ**: SrcList構造体はFROM句のテーブルリストを表す。DELETE文では単一テーブルが対象。

#### Step 2: ユーティリティ関数を理解する

DELETE処理で使用される共通関数を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | delete.c | `src/delete.c` | sqlite3SrcListLookup()、sqlite3IsReadOnly() |

**主要処理フロー**:
1. **31-46行目**: sqlite3SrcListLookup()でテーブルを検索
2. **51-56行目**: sqlite3CodeChangeCount()で変更行数を報告
3. **77-110行目**: tabIsReadOnly()で読み取り専用チェック
4. **119-133行目**: sqlite3IsReadOnly()で書き込み可否を判定

#### Step 3: エントリーポイントを理解する

DELETE処理の起点を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | delete.c | `src/delete.c` | sqlite3DeleteFrom()関数 |

**主要処理フロー**:
- **288-294行目**: sqlite3DeleteFrom()の関数シグネチャ
- pTabList（テーブルリスト）、pWhere（WHERE句）、pOrderBy、pLimit

#### Step 4: ビュー処理を理解する

ビューへのDELETE処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | delete.c | `src/delete.c` | sqlite3MaterializeView()関数 |

**主要処理フロー**:
- **142-170行目**: sqlite3MaterializeView()の実装
- ビューをエフェメラルテーブルに実体化

### プログラム呼び出し階層図

```
sqlite3DeleteFrom()                [delete.c:288]
    │
    ├─ sqlite3SrcListLookup()      [delete.c:31]
    │      └─ テーブル検索
    │
    ├─ sqlite3IsReadOnly()         [delete.c:119]
    │      └─ 書き込み可否チェック
    │
    ├─ sqlite3MaterializeView()    [delete.c:142]（ビューの場合）
    │      └─ ビュー実体化
    │
    ├─ sqlite3LimitWhere()         [delete.c:182]（LIMIT有りの場合）
    │      └─ LIMIT/ORDER BY用サブクエリ生成
    │
    ├─ sqlite3WhereBegin()         [where.c]
    │      └─ WHERE句最適化・対象行スキャン
    │
    ├─ 外部キー処理                 [fkey.c]
    │      └─ カスケード処理
    │
    └─ VDBEコード生成
           ├─ OP_Delete
           └─ インデックス削除
```

### データフロー図

```
[入力]                    [処理]                        [出力]

DELETE文          ───▶ パース・検証            ───▶ テーブル更新
    │                      │
    ▼                      ▼
WHERE条件         ───▶ 対象行特定              ───▶ 行特定
                           │
                           ▼
                     外部キーチェック
                           │
                           ├─▶ CASCADE：連鎖削除
                           │
                           ▼
                     インデックス削除
                           │
                           ▼
                     B-Tree行削除
                           │
                           ▼
                     トリガー実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| delete.c | `src/delete.c` | ソース | DELETE文処理のメイン実装 |
| where.c | `src/where.c` | ソース | WHERE句最適化 |
| fkey.c | `src/fkey.c` | ソース | 外部キー制約処理 |
| trigger.c | `src/trigger.c` | ソース | トリガー処理 |
| vdbe.c | `src/vdbe.c` | ソース | VDBE実行（OP_Delete等） |
| btree.c | `src/btree.c` | ソース | B-Tree操作 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダー | 構造体定義 |
