# バッチ設計書 37-db:schema:load

## 概要

本ドキュメントは、Railsフレームワークが提供するスキーマロード用Rakeタスク `db:schema:load` の設計仕様について記載する。

### 本バッチの処理概要

`db:schema:load` タスクは、スキーマファイル（db/schema.rb または db/structure.sql）をデータベースにロードし、テーブル構造を構築するためのRakeタスクである。マイグレーションを実行せずにデータベースを構築する際に使用する。

**業務上の目的・背景**：新規環境のセットアップや、クリーンな状態からのデータベース構築時に、マイグレーションを順次実行するよりも高速にデータベースを構築するために使用される。スキーマファイルには全てのマイグレーションが適用された最終状態が記録されているため、これをロードすることで即座に最新のスキーマを再現できる。

**バッチの実行タイミング**：以下のタイミングで実行される：
- `db:setup` の一部として自動実行
- 新規環境構築時の手動実行
- テストデータベースの準備時（db:test:load_schema）
- CI/CDパイプラインでのデータベース初期化

**主要な処理内容**：
1. 環境保護チェック（本番環境での実行制限）
2. 現在の環境のすべてのデータベース設定に対してループ処理
3. 各データベースに対して、設定されたフォーマット（ruby/sql）でスキーマをロード
4. Ruby形式の場合：`load` メソッドでschema.rbを評価
5. SQL形式の場合：データベースアダプタの `structure_load` を使用
6. ar_internal_metadata テーブルを更新（環境名とスキーマハッシュを記録）

**前後の処理との関連**：
- 前提：データベースが作成済みであること
- 前提：スキーマファイルが存在すること
- 関連タスク：`db:setup`（create後にschema:loadを呼び出す）
- 関連タスク：`db:schema:dump`（ロード元のスキーマを生成）

**影響範囲**：データベースにテーブル構造が構築される。既存のテーブルがある場合は、スキーマファイルの内容に応じて再構築される。ar_internal_metadataテーブルに環境情報が記録される。

## バッチ種別

データベース管理 / スキーマ構築

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 任意 |
| 実行日 | 任意 |
| トリガー | 手動（bin/rails db:schema:load） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| データベース存在 | 対象データベースが作成済みであること |
| スキーマファイル存在 | db/schema.rb または db/structure.sql が存在すること |
| 環境保護チェック | 本番環境では DISABLE_DATABASE_ENVIRONMENT_CHECK=1 が必要 |

### 実行可否判定

- `check_protected_environments` により本番環境での実行は保護される
- スキーマファイルが存在しない場合はエラー
- schema_dump_pathがnilの場合は処理をスキップ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| RAILS_ENV | 環境変数 | No | development | 対象環境を指定 |
| SCHEMA | 環境変数 | No | db/schema.rb | スキーマファイルのパスを指定 |
| SCHEMA_FORMAT | 環境変数 | No | config設定値 | フォーマット（ruby/sql）を指定 |
| VERBOSE | 環境変数 | No | true | 処理の詳細出力を制御 |
| DISABLE_DATABASE_ENVIRONMENT_CHECK | 環境変数 | No | なし | 本番環境での実行を許可 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| db/schema.rb | Ruby | Ruby形式のスキーマ定義 |
| db/structure.sql | SQL | SQL形式のスキーマ定義 |
| config/database.yml | YAML | データベース接続設定 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| データベース | DB | スキーマに基づいて構築されたテーブル構造 |
| 標準出力 | テキスト | 処理結果メッセージ |

### 出力ファイル仕様

ファイル出力は行わない。データベースへのスキーマロードのみを実行する。

## 処理フロー

### 処理シーケンス

```
1. load_config
   └─ Railsアプリケーションとデータベース設定をロード
2. check_protected_environments
   └─ 本番環境保護のチェック
3. load_schema_current メソッド実行
   └─ 各データベース設定に対してループ処理
4. load_schema メソッド実行（各DB）
   └─ 4.1 フォーマットを決定（ruby/sql）
   └─ 4.2 スキーマファイルのパスを取得
   └─ 4.3 スキーマファイルの存在チェック
   └─ 4.4 VERBOSEモード設定
5. スキーマロード実行
   └─ Ruby形式: load(file) で評価
   └─ SQL形式: structure_load で実行
6. メタデータ更新
   └─ ar_internal_metadata に環境名とschema_sha1を記録
```

### フローチャート

```mermaid
flowchart TD
    A[db:schema:load 開始] --> B[設定ロード]
    B --> C[check_protected_environments]
    C --> D{保護対象環境?}
    D -->|Yes| E[エラー: 保護環境]
    D -->|No| F[load_schema_current]
    F --> G[各DB設定をループ]
    G --> H{スキーマファイル存在?}
    H -->|No| I[エラー: ファイルなし]
    H -->|Yes| J{フォーマット判定}
    J -->|ruby| K[load schema.rb]
    J -->|sql| L[structure_load]
    K --> M[create_table_and_set_flags]
    L --> M
    M --> N[環境名とschema_sha1を記録]
    N --> O[次のDB設定へ]
    O --> P{全DB処理完了?}
    P -->|No| G
    P -->|Yes| Q[db:schema:load 完了]
    E --> R[処理中断]
    I --> R
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| スキーマロード | 全テーブル | CREATE TABLE | テーブル構造を構築 |
| スキーマロード | 全インデックス | CREATE INDEX | インデックスを作成 |
| メタデータ更新 | ar_internal_metadata | INSERT/UPDATE | 環境情報を記録 |
| メタデータ更新 | schema_migrations | INSERT | バージョン情報を記録 |

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

#### ar_internal_metadata

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | key | 'environment' | 環境名を記録 |
| INSERT | value | Rails.env | 現在の環境 |
| INSERT | key | 'schema_sha1' | スキーマファイルのハッシュ |
| INSERT | value | SHA1ハッシュ値 | スキーマ整合性チェック用 |

#### schema_migrations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | version | 全マイグレーションバージョン | スキーマファイルから取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 保護環境エラー | 本番環境で実行を試行 | DISABLE_DATABASE_ENVIRONMENT_CHECK=1 を設定 |
| - | スキーマファイルエラー | スキーマファイルが存在しない | db:migrate を実行してスキーマを生成 |
| - | SyntaxError | schema.rbに文法エラー | スキーマファイルを確認・修正 |
| - | ArgumentError | 不正なフォーマット指定 | ruby または sql を指定 |
| - | ActiveRecordError | DDL実行エラー | スキーマ内容とDB設定を確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（手動タスクのため） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

### 障害時対応

1. エラーメッセージを確認し、原因を特定
2. スキーマファイルの存在と内容を確認
3. データベース接続を確認
4. 保護環境エラーの場合は環境変数を設定
5. 必要に応じて `db:migrate` でスキーマを再生成

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | DDL依存（多くのDBでは自動コミット） |
| コミットタイミング | 各DDL実行時 |
| ロールバック条件 | エラー発生時（部分的ロールバックの可能性あり） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | スキーマ内のテーブル・インデックス数に依存 |
| 目標処理時間 | スキーマサイズに依存（通常数秒〜数十秒） |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

- 同時実行は非推奨
- スキーマロード中は他の接続からのアクセスを避けること
- DDL実行時はテーブルロックが取得される

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | タスク開始時 | （VERBOSEモードで出力） |
| 進捗ログ | 処理中 | CREATE TABLE等のDDL（VERBOSEモード） |
| 終了ログ | タスク終了時 | （VERBOSEモードで出力） |
| エラーログ | エラー発生時 | エラー詳細メッセージ |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | プロジェクトに応じて設定 | 開発者 |
| エラー件数 | 1件以上 | 開発者 |

## 備考

- `structure_load_flags` でアダプタ固有のフラグを指定可能
- Ruby形式（schema.rb）は `ActiveRecord::Schema.define` ブロック内でDDLを実行
- SQL形式（structure.sql）はデータベースクライアントを使用して実行
- マルチデータベース構成では `db:schema:load:データベース名` で個別に実行可能
- `schema_sha1` はスキーマファイルのSHA1ハッシュで、`db:prepare` での整合性チェックに使用
- VERBOSEモードはENV["VERBOSE"]とMigration.verboseの両方がtrueの場合に有効
- テスト環境用には `db:test:load_schema` が用意されている
