# 機能設計書 13-DROP INDEX処理

## 概要

本ドキュメントは、SQLiteにおけるDROP INDEX文の処理機能について記述する。DROP INDEXは、既存のインデックスをデータベーススキーマから削除し、関連するB-Treeストレージを解放する機能である。

### 本機能の処理概要

**業務上の目的・背景**：データベース運用において、不要になったインデックスや、クエリパターンの変更により効果が薄れたインデックスを削除する必要がある。インデックスはデータ更新時にオーバーヘッドを生じるため、使用されないインデックスの削除はデータベース性能の向上に寄与する。また、インデックス構成の見直しやリファクタリング時にも必要な機能である。

**機能の利用シーン**：
- 不要インデックスの削除（クエリパターン変更後）
- インデックスの再作成前の削除（REINDEXの代替）
- データベースファイルサイズの削減
- パフォーマンスチューニング時のインデックス整理

**主要な処理内容**：
1. インデックス名の解決とスキーマ検証
2. インデックスの存在確認
3. UNIQUE/PRIMARY KEY制約インデックスの保護チェック
4. 認証コールバックによるアクセス権限チェック
5. sqlite_schemaテーブルからのメタデータ削除
6. 統計テーブル（sqlite_stat1〜4）からの関連エントリ削除
7. B-Treeルートページの破棄
8. スキーマ変更の確定（スキーマクッキーの更新）

**関連システム・外部連携**：VDBEバイトコードエンジン、B-Treeストレージエンジン、ページャー

**権限による制御**：sqlite3_set_authorizer()で設定された認可コールバックにより、SQLITE_DROP_INDEX、SQLITE_DROP_TEMP_INDEXのアクションコードでアクセス制御が可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接的な画面関連なし（バックエンド処理） |

## 機能種別

DDL操作（データ定義言語） / スキーマ変更 / インデックス削除

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pName | SrcList* | Yes | 削除対象インデックス名（データベース名を含む場合あり） | インデックスの存在確認 |
| ifExists | int | Yes | IF EXISTS指定フラグ | 1の場合、インデックス不存在時もエラーなし |

### 入力データソース

- SQL文解析結果（パーサーから渡されるトークン情報）
- データベーススキーマ（sqlite_schemaテーブル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | 直接的な戻り値なし（エラーはParse構造体に設定） |
| pParse->nErr | int | エラー発生時にインクリメント |
| pParse->checkSchema | int | スキーマ検証フラグ（インデックス不存在時に設定） |

### 出力先

- sqlite_schemaテーブル（メタデータ削除）
- B-Treeストレージ（インデックスページ解放）
- sqlite_statN テーブル（統計情報削除）

## 処理フロー

### 処理シーケンス

```
1. メモリアロケーションチェック
   └─ db->mallocFailed確認

2. スキーマ読み込み
   └─ sqlite3ReadSchema()でデータベーススキーマを読み込み

3. インデックス検索
   └─ sqlite3FindIndex()でインデックスオブジェクトを取得

4. 存在チェック
   └─ 不存在時: ifExists確認、エラー出力または無視

5. 制約インデックスチェック
   └─ idxType != SQLITE_IDXTYPE_APPDEFの場合エラー

6. データベースインデックス取得
   └─ sqlite3SchemaToIndex()

7. 認証チェック
   └─ SQLITE_DELETE (sqlite_schema)
   └─ SQLITE_DROP_INDEX / SQLITE_DROP_TEMP_INDEX

8. VDBEコード生成
   └─ sqlite3BeginWriteOperation()

9. sqlite_schemaから削除
   └─ DELETE FROM sqlite_schema WHERE name=? AND type='index'

10. 統計テーブルクリア
    └─ sqlite3ClearStatTables()

11. スキーマクッキー更新
    └─ sqlite3ChangeCookie()

12. ルートページ破棄
    └─ destroyRootPage()

13. OP_DropIndex命令追加
    └─ インメモリスキーマからの削除
```

### フローチャート

```mermaid
flowchart TD
    A[DROP INDEX開始] --> B{メモリアロケーションOK?}
    B -->|No| Z[終了]
    B -->|Yes| C{スキーマ読み込み成功?}
    C -->|No| Z
    C -->|Yes| D[インデックス検索]
    D --> E{インデックス存在?}
    E -->|No| F{IF EXISTS指定?}
    F -->|Yes| G[スキーマ検証フラグ設定]
    G --> Z
    F -->|No| H[エラー: no such index]
    H --> Z
    E -->|Yes| I{UNIQUE/PRIMARY KEY制約?}
    I -->|Yes| J[エラー: cannot be dropped]
    J --> Z
    I -->|No| K[認証チェック]
    K --> L{認証成功?}
    L -->|No| Z
    L -->|Yes| M[VDBE取得]
    M --> N[書き込みトランザクション開始]
    N --> O[sqlite_schemaから削除]
    O --> P[統計テーブルクリア]
    P --> Q[スキーマクッキー更新]
    Q --> R[ルートページ破棄]
    R --> S[OP_DropIndex命令追加]
    S --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-13-01 | 制約インデックス保護 | UNIQUE/PRIMARY KEY制約で自動作成されたインデックスは削除不可 | idxType != SQLITE_IDXTYPE_APPDEF |
| BR-13-02 | IF EXISTS | IF EXISTS指定時、インデックス不存在でもエラーにしない | IF EXISTS指定時 |
| BR-13-03 | スキーマ検証 | インデックス不存在時はpParse->checkSchema=1を設定 | 不存在時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| メタデータ削除 | sqlite_schema | DELETE | インデックス定義を削除 |
| 統計情報削除 | sqlite_stat1〜4 | DELETE | インデックス統計情報を削除 |
| インデックス破棄 | 対象インデックス | 全データ削除 | B-Treeルートページを破棄 |

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

#### sqlite_schema

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | name=%Q AND type='index' | インデックス名で特定 |

#### sqlite_stat1〜4

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | idx=%Q | 統計テーブルが存在する場合のみ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | no such index: %S | インデックスが存在しない（IF EXISTSなし） | 正しいインデックス名を指定、またはIF EXISTS使用 |
| - | index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped | 制約インデックスの削除試行 | 制約自体を削除するにはテーブル再作成が必要 |
| SQLITE_AUTH | 認証エラー | authorizerコールバックが拒否 | 権限を確認 |

### リトライ仕様

DROP INDEXはアトミック操作であり、失敗時は自動ロールバックされる。明示的なリトライ機構は提供されない。

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

- 書き込みトランザクション内で実行される
- sqlite3BeginWriteOperation()により排他ロックを取得
- スキーマクッキーが更新され、他の接続のキャッシュが無効化される
- エラー発生時は全変更がロールバックされる

## パフォーマンス要件

- インデックスサイズに比例した処理時間（B-Tree破棄のため）
- auto_vacuumモードでページ再編成が発生する可能性あり

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

- sqlite3_set_authorizer()コールバックによるアクセス制御
- SQLITE_DROP_INDEX / SQLITE_DROP_TEMP_INDEX アクションでの認可
- sqlite_schemaへのDELETE権限チェック

## 備考

- UNIQUE/PRIMARY KEY制約で作成されたインデックスを削除するには、ALTER TABLEでテーブルを再作成する必要がある
- DROP INDEXはDDL文であり、暗黙的にトランザクションをコミットする

---

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

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

### 推奨読解順序

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

まず、DROP INDEX処理で使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | Index構造体（idxType, tnum, pSchema等） |
| 1-2 | sqliteInt.h | `src/sqliteInt.h` | SrcList構造体（インデックス名指定用） |

**読解のコツ**: Index構造体のidxTypeフィールドは、SQLITE_IDXTYPE_APPDEF（ユーザー定義）、SQLITE_IDXTYPE_UNIQUE（UNIQUE制約）、SQLITE_IDXTYPE_PRIMARYKEY（PRIMARY KEY制約）の3種類がある。APPDEFのみ削除可能。

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

処理の起点となる関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | build.c | `src/build.c` | sqlite3DropIndex()関数（4590行目〜）がエントリーポイント |

**主要処理フロー**:
1. **4596-4598行目**: メモリアロケーションチェック
2. **4603-4604行目**: sqlite3ReadSchema()でスキーマ読み込み
3. **4606行目**: sqlite3FindIndex()でインデックス検索
4. **4607-4616行目**: インデックス不存在時の処理
5. **4617-4621行目**: 制約インデックスチェック（idxType != SQLITE_IDXTYPE_APPDEF）
6. **4622行目**: sqlite3SchemaToIndex()でデータベースインデックス取得
7. **4623-4636行目**: 認証チェック（SQLITE_DELETE, SQLITE_DROP_INDEX）
8. **4640-4651行目**: VDBEコード生成

#### Step 3: 削除処理の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | build.c | `src/build.c` | 4641-4651行目のVDBEコード生成部分 |

**主要処理フロー**:
- **4642行目**: sqlite3BeginWriteOperation()で書き込みトランザクション開始
- **4643-4646行目**: sqlite3NestedParse()でDELETE文生成
- **4647行目**: sqlite3ClearStatTables()で統計テーブルクリア
- **4648行目**: sqlite3ChangeCookie()でスキーマクッキー更新
- **4649行目**: destroyRootPage()でB-Treeルートページ破棄
- **4650行目**: OP_DropIndex命令追加

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

```
sqlite3DropIndex() [build.c:4590]
    │
    ├─ sqlite3ReadSchema() [prepare.c]
    │      └─ スキーマ読み込み
    │
    ├─ sqlite3FindIndex() [build.c]
    │      └─ インデックスオブジェクト検索
    │
    ├─ sqlite3SchemaToIndex() [callback.c]
    │      └─ スキーマからDB番号取得
    │
    ├─ sqlite3AuthCheck() [auth.c]
    │      ├─ SQLITE_DELETE チェック
    │      └─ SQLITE_DROP_INDEX チェック
    │
    ├─ sqlite3GetVdbe() [vdbeaux.c]
    │
    ├─ sqlite3BeginWriteOperation() [build.c]
    │
    ├─ sqlite3NestedParse() [build.c:293]
    │      └─ DELETE FROM sqlite_schema
    │
    ├─ sqlite3ClearStatTables() [build.c:3359]
    │      └─ DELETE FROM sqlite_stat1〜4
    │
    ├─ sqlite3ChangeCookie() [build.c]
    │
    ├─ destroyRootPage() [build.c]
    │      └─ B-Treeルートページ破棄
    │
    └─ OP_DropIndex
           └─ インメモリスキーマ更新
```

### データフロー図

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

DROP INDEX文 ──────▶ パーサー ──────────────▶ Parse構造体
                          │
                          ▼
               sqlite3DropIndex()
                          │
           ┌──────────────┼──────────────┐
           ▼              ▼              ▼
    インデックス     制約チェック    認証チェック
       検索          (idxType)
           │              │              │
           └──────────────┼──────────────┘
                          ▼
                   VDBEコード生成
                          │
           ┌──────────────┼──────────────┐
           ▼              ▼              ▼
    sqlite_schema    sqlite_stat*    B-Tree
       削除           統計削除      ルートページ
                                      破棄
           │              │              │
           └──────────────┼──────────────┘
                          ▼
               OP_DropIndex ──────▶ スキーマ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| build.c | `src/build.c` | ソース | DROP INDEX主要処理、sqlite3DropIndex() |
| auth.c | `src/auth.c` | ソース | 認証処理 |
| vdbeaux.c | `src/vdbeaux.c` | ソース | VDBEヘルパー関数 |
| btree.c | `src/btree.c` | ソース | B-Tree操作（ルートページ破棄） |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダー | Index構造体定義、idxType定数 |
| vdbe.h | `src/vdbe.h` | ヘッダー | VDBE命令定義（OP_DropIndex） |
