# 機能設計書 39-RBU

## 概要

本ドキュメントは、SQLiteにおけるRBU（Resumable Bulk Update）機能の設計仕様を定義する。大量のデータ更新を中断・再開可能な形式で実行する拡張機能である。

### 本機能の処理概要

RBUは、大量のINSERT/UPDATE/DELETE操作を、既存のデータベース読み取りをブロックすることなく、かつ中断・再開可能な形式で実行する機能である。

**業務上の目的・背景**：組み込みシステムや大規模データベースでは、数百万件のレコードを更新する際に以下の課題がある：(1)長時間のロックによる他の読み取り操作のブロック、(2)更新中の電源断によるデータ不整合、(3)限られたメモリでの大量データ処理。RBUはこれらの課題を解決する。

**機能の利用シーン**：
- 組み込み機器のファームウェア更新時のDB更新
- モバイルアプリのオフライン同期での大量データ取り込み
- 定期的なマスターデータの一括更新
- データマイグレーション

**主要な処理内容**：
1. RBUデータベース（更新内容を格納したDB）を準備
2. sqlite3rbu_open()でRBUハンドルを作成
3. sqlite3rbu_step()を繰り返し呼び出して更新を進行
4. 各ステップで状態をRBUデータベースに保存（中断・再開可能）
5. 更新完了後、*-oalファイルを*-walファイルにリネーム
6. チェックポイントでWALを本体にマージ

**関連システム・外部連携**：
- WALモード：RBUは*-oalファイル（off-line WAL）を使用
- VFS層：imposterテーブルを使用したB-Tree直接操作
- チェックポイント機能：最終段階でのWALマージ

**権限による制御**：
- RBUデータベースへの読み取りアクセスが必要
- 対象データベースへの排他書き込みアクセスが必要（最終段階）

## 関連画面

本機能はSQLite内部機能のため、直接的な画面関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

バルク更新 / 中断再開 / オフライン更新

## 入力仕様

### 入力パラメータ（RBUオープン）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| zTarget | const char* | Yes | 更新対象DBのパス | 有効なパス |
| zRbu | const char* | Yes | RBUデータベースのパス | 有効なパス |
| zState | const char* | No | 状態DBのパス（NULLでRBU DB内に保存） | - |

### RBUデータベース構造

| テーブル名 | 説明 |
|-----------|------|
| data_テーブル名 | 各対象テーブルに対応する更新データテーブル |
| rbu_control | 操作種別（0=INSERT, 1=DELETE, 2〜=UPDATE） |

```sql
-- RBUデータベースの例
CREATE TABLE data_mytable(
  col1, col2, col3,           -- 対象テーブルと同じカラム
  rbu_control                 -- 操作種別
);
INSERT INTO data_mytable VALUES('a', 'b', 'c', 0);  -- INSERT
INSERT INTO data_mytable VALUES('x', NULL, 'z', '.x.');  -- UPDATEでcol2を更新
```

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SQLITE_OK | int | ステップ成功（継続可能） |
| SQLITE_DONE | int | 全更新完了 |
| SQLITE_ERROR | int | エラー発生 |
| progress | sqlite3_int64 | 進捗（ステップ数） |
| state | int | 現在のステージ |

### RBUステージ

| ステージ | 値 | 説明 |
|---------|-----|------|
| RBU_STAGE_OAL | 1 | *-oalファイルを構築中 |
| RBU_STAGE_MOVE | 2 | *-oalを*-walにリネーム |
| RBU_STAGE_CAPTURE | 3 | （内部使用） |
| RBU_STAGE_CKPT | 4 | チェックポイント中 |
| RBU_STAGE_DONE | 5 | 完了 |

## 処理フロー

### 処理シーケンス

```
1. RBUデータベース準備フェーズ
   ├─ 対象テーブルごとにdata_xxxテーブルを作成
   ├─ 更新データとrbu_controlを投入
   └─ INSERT=0, DELETE=1, UPDATE=文字列マスク

2. OAL構築フェーズ（STAGE_OAL）
   ├─ 対象DBはロールバックモードで読み取り継続可能
   ├─ RBUがimposterテーブル経由でB-Treeを直接更新
   ├─ 更新結果を*-oalファイルに書き込み
   └─ 各ステップで状態を保存（中断可能）

3. リネームフェーズ（STAGE_MOVE）
   ├─ 対象DBに排他ロックを取得
   ├─ *-oalを*-walにリネーム
   └─ 他のリーダーは新しいWALを認識

4. チェックポイントフェーズ（STAGE_CKPT）
   ├─ WALを本体DBにマージ
   ├─ 各ステップで1フレームずつチェックポイント
   └─ 中断・再開可能

5. 完了フェーズ（STAGE_DONE）
   └─ RBUハンドルをクローズ
```

### フローチャート

```mermaid
flowchart TD
    A[RBUデータベース準備] --> B[sqlite3rbu_open]
    B --> C[STAGE_OAL: *-oal構築]
    C --> D{sqlite3rbu_step}
    D -->|SQLITE_OK| E[状態保存]
    E --> D
    D -->|中断| F[sqlite3rbu_close]
    F --> G[後で再開可能]
    D -->|STAGE完了| H{次のステージ?}
    H -->|STAGE_MOVE| I[*-oal → *-wal リネーム]
    I --> J[STAGE_CKPT: チェックポイント]
    J --> K{sqlite3rbu_step}
    K -->|SQLITE_OK| J
    K -->|SQLITE_DONE| L[完了]
    H -->|STAGE_DONE| L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-39-1 | 読み取り継続 | STAGE_OAL中、対象DBは読み取り可能 | OAL構築中 |
| BR-39-2 | 排他ロック | STAGE_MOVE開始時に排他ロックを取得 | リネーム時 |
| BR-39-3 | 状態永続化 | 各ステップで状態をRBU DBに保存 | 常時 |
| BR-39-4 | ソート順更新 | 各B-Treeはキー順にソートされた順序で更新 | OAL構築中 |
| BR-39-5 | Imposterテーブル | B-Tree直接操作にimposterテーブルを使用 | OAL構築中 |

### 計算ロジック

**rbu_control解釈**：
- 整数0: INSERT（新規行挿入）
- 整数1: DELETE（行削除）
- 文字列 'x' or '.': UPDATEで 'x'=変更カラム、'.'=変更なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| READ | RBUデータベース | SELECT | data_xxxテーブルから更新データ読み取り |
| WRITE | 対象データベース | B-Tree操作 | imposterテーブル経由で更新 |
| WRITE | *-oalファイル | WAL書き込み | 更新結果の一時保存 |
| WRITE | rbu_state | INSERT/UPDATE | 進捗状態の保存 |

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

#### rbu_state（RBUデータベース内）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | k | ステートキー | 固定キー |
| INSERT/UPDATE | v | 状態値 | ステージ、進捗等 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_ERROR | 構造エラー | RBU DBに必要なテーブルがない | data_xxxテーブルを作成 |
| SQLITE_BUSY | ロック競合 | 対象DBがロック中 | リトライまたは待機 |
| SQLITE_CONSTRAINT | 制約違反 | UNIQUE/FK制約違反 | データ修正 |
| SQLITE_IOERR | I/Oエラー | ディスクエラー | ディスク状態確認 |
| SQLITE_CORRUPT | 破損 | *-oalまたは対象DB破損 | RBU DBから再開 |

### リトライ仕様

- SQLITE_BUSY時は自動リトライ可能
- その他のエラー時はsqlite3rbu_close()でクローズし、状態を調査
- 致命的でないエラーからは状態を保持して再開可能

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

- RBU更新中、対象DBはロールバックモードで読み取り可能
- STAGE_MOVE以降は排他アクセス
- RBU自体は内部的にトランザクションを管理
- 電源断時はrbu_stateから状態を復元して再開

## パフォーマンス要件

- B-Treeをキー順にソートして更新することでI/Oを最小化
- imposterテーブルによりインデックス維持のオーバーヘッドを削減
- 各sqlite3rbu_step()は約1行の更新を処理
- チェックポイント時は1フレーム/ステップで制御可能

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

- RBUデータベースの整合性を信頼する必要がある
- 不正なRBU DBは対象DBを破損させる可能性がある
- RBU処理中の電源断に対して耐性あり（状態復元可能）

## 備考

- SQLITE_ENABLE_RBUでコンパイル時に有効化
- sqlite3rbu_vacuum()でVACUUM操作も可能
- rbu_exclusive_checkpointオプションで排他チェックポイント
- 対象DBがWALモードの場合でも動作（一時的にロールバックモードに切り替え）

---

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

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

### 推奨読解順序

#### Step 1: 概要とアーキテクチャを理解する

RBUの全体設計を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqlite3rbu.c | `ext/rbu/sqlite3rbu.c` | 14-81行目のOVERVIEWコメント |
| 1-2 | sqlite3rbu.h | `ext/rbu/sqlite3rbu.h` | 公開API定義 |

**読解のコツ**: OVERVIEWコメントに3つのステージ（OAL構築、リネーム、チェックポイント）が詳細に説明されている。特に「imposterテーブル」の概念が重要。

#### Step 2: 状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sqlite3rbu.c | `ext/rbu/sqlite3rbu.c` | 120-178行目のrbu_state定義とRbuState構造体 |

**主要処理フロー**:
- RBU_STATE_STAGE〜RBU_STATE_DATATBLの各状態キー
- RBU_STAGE_OAL〜RBU_STAGE_DONEの各ステージ

#### Step 3: オブジェクトイテレーターを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sqlite3rbu.c | `ext/rbu/sqlite3rbu.c` | 243-298行目のRbuObjIter構造体 |

**主要処理フロー**:
- 対象テーブル→インデックス→クリーンアップの順でイテレート
- imposterテーブルとの関連

#### Step 4: メイン処理ループを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sqlite3rbu.c | `ext/rbu/sqlite3rbu.c` | sqlite3rbu_step()関数 |

**主要処理フロー**:
- 現在のステージに応じた処理分岐
- OAL構築、リネーム、チェックポイントの各処理
- 状態保存とエラー処理

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

```
sqlite3rbu_open()
    │
    ├─ RBU DBをオープン
    ├─ rbu_stateから状態を復元（再開時）
    └─ 対象DBをオープン

sqlite3rbu_step()
    │
    ├─ [STAGE_OAL]
    │      ├─ rbuObjIterNext()  次のテーブル/インデックス
    │      ├─ rbuObjIterPrepareAll()  imposterテーブル準備
    │      └─ rbuStepOneOp()  1行更新
    │
    ├─ [STAGE_MOVE]
    │      └─ rename("*-oal", "*-wal")  リネーム
    │
    └─ [STAGE_CKPT]
           └─ sqlite3_wal_checkpoint_v2()  1フレームチェックポイント

sqlite3rbu_close()
    │
    ├─ 状態をrbu_stateに保存
    └─ ハンドル解放
```

### データフロー図

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

RBU DB ────────────────────▶ sqlite3rbu_open() ─────────────▶ rbu_handle
(data_xxx, rbu_state)       初期化/状態復元

rbu_handle ────────────────▶ sqlite3rbu_step() ─────────────▶ SQLITE_OK/DONE
                           │
[STAGE_OAL]                ├─ imposterテーブル更新 ────────▶ *-oalファイル
                           │
[STAGE_MOVE]               ├─ rename() ────────────────────▶ *-walファイル
                           │
[STAGE_CKPT]               └─ checkpoint ──────────────────▶ 対象DB更新

rbu_handle ────────────────▶ sqlite3rbu_close() ────────────▶ rbu_state更新
                           状態保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sqlite3rbu.c | `ext/rbu/sqlite3rbu.c` | ソース | RBUメイン実装 |
| sqlite3rbu.h | `ext/rbu/sqlite3rbu.h` | ヘッダー | 公開API定義 |
| rbu.c | `ext/rbu/rbu.c` | ソース | RBUシェルツール |
| test_rbu.c | `ext/rbu/test_rbu.c` | ソース | テスト用実装 |
