# 機能設計書 14-ALTER TABLE処理

## 概要

本ドキュメントは、SQLiteにおけるALTER TABLE文の処理機能について記述する。ALTER TABLEは、既存テーブルの構造を変更する機能であり、テーブル名の変更（RENAME TO）、列の追加（ADD COLUMN）、列名の変更（RENAME COLUMN）、列の削除（DROP COLUMN）をサポートする。

### 本機能の処理概要

**業務上の目的・背景**：アプリケーションの進化に伴い、データベーススキーマの変更が必要になることがある。ALTER TABLE機能は、既存データを保持したままテーブル構造を変更できるため、本番環境でのスキーママイグレーションに不可欠である。特にモバイルアプリやデスクトップアプリでは、アプリケーションアップデート時のデータベースバージョンアップに広く使用される。

**機能の利用シーン**：
- アプリケーションバージョンアップ時のスキーマ変更
- 新しい列の追加（機能拡張対応）
- テーブル名/列名のリファクタリング
- 不要列の削除

**主要な処理内容**：
1. **RENAME TO**: テーブル名変更、関連オブジェクト（インデックス、トリガー、ビュー）のSQL文更新
2. **ADD COLUMN**: 新しい列の追加、デフォルト値の検証、制約の適用
3. **RENAME COLUMN**: 列名変更、関連オブジェクトのSQL文更新
4. **DROP COLUMN**: 列の削除（テーブル再構築が必要な場合あり）

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

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

## 関連画面

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

## 機能種別

DDL操作（データ定義言語） / スキーマ変更

## 入力仕様

### 入力パラメータ

#### RENAME TO

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pSrc | SrcList* | Yes | 変更対象テーブル名 | テーブルの存在確認 |
| pName | Token* | Yes | 新しいテーブル名 | 名前重複チェック |

#### ADD COLUMN

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pSrc | SrcList* | Yes | 変更対象テーブル名 | テーブルの存在確認 |
| pColDef | Token* | Yes | 列定義テキスト | 制約検証 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | 直接的な戻り値なし |
| pParse->nErr | int | エラー発生時にインクリメント |
| pParse->pNewTable | Table* | ADD COLUMN時の新テーブル構造 |

### 出力先

- sqlite_schemaテーブル（メタデータ更新）
- sqlite_sequenceテーブル（RENAME TO時のAUTOINCREMENT情報更新）
- メモリ内スキーマ

## 処理フロー

### 処理シーケンス（RENAME TO）

```
1. テーブル検索
   └─ sqlite3LocateTableItem()で対象テーブル取得

2. 新名前検証
   └─ 同名テーブル/インデックスの存在チェック

3. システムテーブルチェック
   └─ sqlite_*テーブルは変更不可

4. VIEWチェック
   └─ VIEWは名前変更不可

5. 認証チェック
   └─ SQLITE_ALTER_TABLE

6. 仮想テーブル処理
   └─ xRename()コールバック呼び出し

7. sqlite_schema更新
   └─ sqlite_rename_table()でSQL文を更新

8. tbl_name/name列更新
   └─ インデックス名の自動更新含む

9. sqlite_sequence更新
   └─ AUTOINCREMENT情報の名前更新

10. TEMPスキーマ更新
    └─ 関連ビュー/トリガーのSQL更新

11. スキーマリロード
    └─ renameReloadSchema()
```

### 処理シーケンス（ADD COLUMN）

```
1. テーブル検索
   └─ sqlite3LocateTableItem()

2. テーブルコピー作成
   └─ pParse->pNewTableに部分コピー

3. 列定義解析
   └─ sqlite3AddColumn()等で新列定義

4. 制約検証
   └─ PRIMARY KEY、UNIQUE、NOT NULL等

5. デフォルト値検証
   └─ 定数式のみ許可

6. sqlite_schema更新
   └─ CREATE TABLE文の更新

7. スキーマファイルフォーマット検証
   └─ バージョン3以上に更新

8. スキーマリロード
   └─ renameReloadSchema()

9. 制約チェック
   └─ CHECK制約、NOT NULL制約の検証
```

### フローチャート（RENAME TO）

```mermaid
flowchart TD
    A[ALTER TABLE RENAME開始] --> B[テーブル検索]
    B --> C{テーブル存在?}
    C -->|No| Z[終了]
    C -->|Yes| D{新名前重複?}
    D -->|Yes| E[エラー: already exists]
    E --> Z
    D -->|No| F{システムテーブル?}
    F -->|Yes| G[エラー: may not be altered]
    G --> Z
    F -->|No| H{VIEW?}
    H -->|Yes| I[エラー: may not be altered]
    I --> Z
    H -->|No| J[認証チェック]
    J --> K{認証成功?}
    K -->|No| Z
    K -->|Yes| L{仮想テーブル?}
    L -->|Yes| M[xRename()呼び出し]
    L -->|No| N[sqlite_schema更新]
    M --> N
    N --> O[sqlite_sequence更新]
    O --> P[TEMPスキーマ更新]
    P --> Q[スキーマリロード]
    Q --> R[スキーマ検証]
    R --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | システムテーブル禁止 | sqlite_*テーブルは変更不可 | 常時 |
| BR-14-02 | VIEW禁止 | VIEWはALTER TABLE不可 | RENAME TO |
| BR-14-03 | 仮想テーブル禁止 | VIRTUAL TABLEはADD COLUMN不可 | ADD COLUMN |
| BR-14-04 | PRIMARY KEY禁止 | ADD COLUMNでPRIMARY KEYは追加不可 | ADD COLUMN |
| BR-14-05 | UNIQUE禁止 | ADD COLUMNでUNIQUEは追加不可 | ADD COLUMN |
| BR-14-06 | NOT NULL制限 | NOT NULL列はデフォルト値必須 | ADD COLUMN |
| BR-14-07 | REFERENCES制限 | REFERENCES列はデフォルト値NULL必須 | ADD COLUMN（外部キー有効時） |
| BR-14-08 | STORED禁止 | STOREDの生成列は追加不可（空テーブルを除く） | ADD COLUMN |
| BR-14-09 | 定数デフォルト | デフォルト値は定数式のみ（CURRENT_TIME等は不可） | ADD COLUMN |
| BR-14-10 | エポニマステーブル禁止 | エポニマス仮想テーブルは変更不可 | 常時 |
| BR-14-11 | シャドウテーブル禁止 | Defensiveモード時、シャドウテーブルは変更不可 | Defensiveモード |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| RENAME TO | sqlite_schema | UPDATE | SQL文、tbl_name、nameの更新 |
| RENAME TO | sqlite_sequence | UPDATE | シーケンス名の更新 |
| RENAME TO | temp.sqlite_schema | UPDATE | TEMP関連オブジェクトの更新 |
| ADD COLUMN | sqlite_schema | UPDATE | CREATE TABLE文の更新 |

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

#### sqlite_schema（RENAME TO）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sql | sqlite_rename_table()で変換 | SQL文内のテーブル名更新 |
| UPDATE | tbl_name | 新テーブル名 | 関連オブジェクトのtbl_name |
| UPDATE | name | 新テーブル名/自動インデックス名 | 条件付き |

#### sqlite_schema（ADD COLUMN）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sql | printf()で列定義追加 | CREATE TABLE文の拡張 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | table %s may not be altered | システムテーブル等 | 対象テーブルを確認 |
| - | view %s may not be altered | VIEWのRENAME試行 | テーブルを指定 |
| - | virtual tables may not be altered | 仮想テーブルのADD COLUMN | 仮想テーブルでは不可 |
| - | there is already another table or index with this name | 名前重複 | 別名を使用 |
| - | Cannot add a PRIMARY KEY column | PRIMARY KEY列追加試行 | テーブル再作成が必要 |
| - | Cannot add a UNIQUE column | UNIQUE列追加試行 | テーブル再作成が必要 |
| - | Cannot add a NOT NULL column with default value NULL | NOT NULL制約違反 | デフォルト値を指定 |
| - | Cannot add a REFERENCES column with non-NULL default value | 外部キー制約違反 | デフォルト値をNULLに |
| - | Cannot add a column with non-constant default | 非定数デフォルト | 定数式を使用 |
| - | cannot add a STORED column | STORED列追加試行 | テーブル再作成が必要 |
| SQLITE_AUTH | 認証エラー | authorizerが拒否 | 権限を確認 |

### リトライ仕様

ALTER TABLEはアトミック操作であり、失敗時は自動ロールバックされる。

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

- 書き込みトランザクション内で実行される
- スキーマクッキーが更新される
- sqlite3MayAbort()が呼ばれ、エラー時はアボート可能

## パフォーマンス要件

- RENAME TO: テーブルサイズに依存しない（メタデータのみ更新）
- ADD COLUMN: テーブルサイズに依存しない（メタデータのみ更新、ただし制約検証時は全行スキャン）
- DROP COLUMN: テーブル再構築が必要な場合、テーブルサイズに比例

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

- sqlite3_set_authorizer()コールバックによるアクセス制御
- SQLITE_ALTER_TABLEアクションでの認可
- システムテーブル・シャドウテーブルの保護

## 備考

- ADD COLUMNで追加された列は、既存行ではデフォルト値またはNULLとなる
- SQLiteのALTER TABLEは他のRDBMSに比べ機能が限定的
- DROP COLUMNは内部的にテーブル再構築を行う場合がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | Table構造体、Column構造体の定義 |

**読解のコツ**: Column構造体のcolFlagsフィールドには、COLFLAG_PRIMKEY、COLFLAG_UNIQUE、COLFLAG_GENERATED等の重要なフラグが格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | alter.c | `src/alter.c` | sqlite3AlterRenameTable()関数（124行目〜）がRENAME TOのエントリーポイント |

**主要処理フロー**:
1. **143-146行目**: テーブル検索とデータベース特定
2. **155-162行目**: 新名前の重複チェック
3. **167-172行目**: システムテーブル・予約名チェック（isAlterableTable）
4. **175-178行目**: VIEWチェック
5. **183-185行目**: 認証チェック（SQLITE_ALTER_TABLE）
6. **192-197行目**: 仮想テーブルのxRename準備
7. **216-222行目**: sqlite_schema更新（sqlite_rename_table関数使用）
8. **226-240行目**: tbl_name, name列の更新
9. **246-250行目**: sqlite_sequence更新（AUTOINCREMENT）
10. **256-266行目**: TEMPスキーマ更新
11. **281-282行目**: スキーマリロードとテスト

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | alter.c | `src/alter.c` | sqlite3AlterBeginAddColumn()（483行目〜）とsqlite3AlterFinishAddColumn()（313行目〜） |

**主要処理フロー（BeginAddColumn）**:
- **495-496行目**: テーブル検索
- **499-502行目**: 仮想テーブルチェック
- テーブルの部分コピー作成

**主要処理フロー（FinishAddColumn）**:
- **354-362行目**: PRIMARY KEY、UNIQUEチェック
- **377-380行目**: NOT NULLとデフォルト値チェック
- **386-400行目**: デフォルト値の定数チェック
- **417-424行目**: sqlite_schema UPDATE文生成
- **447-464行目**: 制約検証（CHECK、NOT NULL、STRICT）

#### Step 4: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | alter.c | `src/alter.c` | isAlterableTable()（31行目〜）- システムテーブルチェック |
| 4-2 | alter.c | `src/alter.c` | renameTestSchema()（53行目〜）- スキーマ検証 |
| 4-3 | alter.c | `src/alter.c` | renameReloadSchema()（111行目〜）- スキーマリロード |

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

```
sqlite3AlterRenameTable() [alter.c:124]
    │
    ├─ sqlite3LocateTableItem() [build.c:481]
    │
    ├─ isAlterableTable() [alter.c:31]
    │      └─ sqlite3ReadOnlyShadowTables() [build.c:3455]
    │
    ├─ sqlite3AuthCheck() [auth.c]
    │
    ├─ sqlite3NestedParse() [build.c:293]
    │      ├─ UPDATE sqlite_schema SET sql=sqlite_rename_table(...)
    │      ├─ UPDATE sqlite_schema SET tbl_name=..., name=...
    │      └─ UPDATE sqlite_sequence SET name=...
    │
    ├─ OP_VRename (仮想テーブル時)
    │
    ├─ renameReloadSchema() [alter.c:111]
    │      ├─ sqlite3ChangeCookie()
    │      └─ OP_ParseSchema
    │
    └─ renameTestSchema() [alter.c:53]

sqlite3AlterFinishAddColumn() [alter.c:313]
    │
    ├─ sqlite3AuthCheck() [auth.c]
    │
    ├─ sqlite3ErrorIfNotEmpty() [alter.c:293]
    │      └─ 空テーブルチェック用SELECT/RAISE
    │
    ├─ sqlite3ValueFromExpr() [vdbemem.c]
    │      └─ デフォルト値の定数評価
    │
    ├─ sqlite3NestedParse() [build.c:293]
    │      └─ UPDATE sqlite_schema SET sql=printf(...)
    │
    ├─ renameReloadSchema() [alter.c:111]
    │
    └─ pragma_quick_check (制約検証)
```

### データフロー図

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

ALTER TABLE文 ─────▶ パーサー ─────────────▶ Parse構造体
                          │
        ┌─────────────────┼─────────────────┐
        ▼                 ▼                 ▼
   RENAME TO        ADD COLUMN        RENAME COLUMN
        │                 │                 │
        ▼                 ▼                 ▼
   テーブル検索      テーブルコピー      列検索
        │                 │                 │
        ▼                 ▼                 ▼
   名前検証         制約検証          名前検証
        │                 │                 │
        └─────────────────┼─────────────────┘
                          ▼
               sqlite_schema更新
                          │
                          ▼
               スキーマリロード ──────▶ 新スキーマ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| alter.c | `src/alter.c` | ソース | ALTER TABLE主要処理 |
| build.c | `src/build.c` | ソース | sqlite3NestedParse()、sqlite3AddColumn()等 |
| auth.c | `src/auth.c` | ソース | 認証処理 |
| vdbemem.c | `src/vdbemem.c` | ソース | sqlite3ValueFromExpr()（デフォルト値評価） |
| func.c | `src/func.c` | ソース | sqlite_rename_table()等のSQL関数 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダー | Table, Column構造体定義 |
