# 機能設計書 26-CSVファイルサポート

## 概要

本ドキュメントは、Apache SparkにおけるCSVファイルの読み込み・書き出し機能の設計について記述する。スキーマ推論やヘッダー処理に対応し、テキストベースの表形式データを効率的に処理する。

### 本機能の処理概要

SparkのCSVサポートは、CSV（Comma-Separated Values）形式のテキストファイルの読み込みと書き出しを提供する。Univocityパーサーライブラリを基盤として、多様なCSV方言（区切り文字、引用符、エスケープ文字等）に対応する。スキーマ推論機能により、カラム名と型をデータから自動推定できる。

**業務上の目的・背景**：CSVは最も広く使用されるデータ交換フォーマットの一つであり、レガシーシステムからのデータ移行、外部システムとのデータ連携、ユーザーによるデータのアップロード・ダウンロード等で頻繁に使用される。SparkのCSVサポートにより、これらのテキストデータをSpark SQLの構造化データとして効率的に処理できる。

**機能の利用シーン**：レガシーシステムからのCSVデータ取り込み、データ分析結果のCSV出力、外部ツールとのデータ交換、ログファイルの解析。

**主要な処理内容**：
1. CSVファイルの読み込み（UnivocityParser使用）
2. スキーマ推論（CSVInferSchema使用）
3. ヘッダー行の処理（CSVHeaderChecker使用）
4. 多様なCSV方言への対応（区切り文字、引用符、エスケープ等）
5. CSVファイルの書き出し（UnivocityGenerator使用）
6. 破損レコードの処理（columnNameOfCorruptRecord）
7. マルチライン対応

**関連システム・外部連携**：Univocityパーサーライブラリ、Hadoop FileSystem API

**権限による制御**：ファイルシステムのアクセス権限に依存。

## 関連画面

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

## 機能種別

データ連携 / ファイルI/O / データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | String | Yes | CSVファイルパス | 有効なファイルシステムパス |
| sep | String | No | 区切り文字（デフォルト: ","） | 単一文字 |
| header | Boolean | No | ヘッダー行の有無（デフォルト: false） | true/false |
| inferSchema | Boolean | No | スキーマ推論（デフォルト: false） | true/false |
| encoding | String | No | 文字エンコーディング（デフォルト: UTF-8） | 有効なエンコーディング名 |
| quote | String | No | 引用符文字（デフォルト: '"'） | 単一文字 |
| escape | String | No | エスケープ文字（デフォルト: '\\'） | 単一文字 |
| multiLine | Boolean | No | マルチライン対応（デフォルト: false） | true/false |
| dateFormat | String | No | 日付フォーマット | 有効な日付パターン |
| timestampFormat | String | No | タイムスタンプフォーマット | 有効なタイムスタンプパターン |
| mode | String | No | パースモード（PERMISSIVE/DROPMALFORMED/FAILFAST） | 列挙値 |
| nullValue | String | No | NULL値の文字列表現 | 任意の文字列 |
| columnNameOfCorruptRecord | String | No | 破損レコード格納カラム名 | 有効なカラム名 |

### 入力データソース

- Hadoop互換ファイルシステム上のCSVファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DataFrame | Dataset[Row] | 読み込まれたCSVデータ |

### 出力先

- DataFrame/Dataset（読み取り結果）
- Hadoop互換ファイルシステム上のCSVファイル（書き出し結果）

## 処理フロー

### 処理シーケンス

```
1. CSVOptions解析
   └─ パラメータをCaseInsensitiveMapで管理
2. スキーマ決定
   └─ ユーザー指定スキーマまたはCSVInferSchemaによる推論
3. ヘッダー処理
   └─ CSVHeaderCheckerによるヘッダー行の検証
4. データ解析
   └─ UnivocityParserによるCSV行の解析
5. 型変換
   └─ 推論/指定スキーマに基づくデータ型変換
6. 書き出し
   └─ UnivocityGeneratorによるCSV行の生成
```

### フローチャート

```mermaid
flowchart TD
    A[spark.read.csv] --> B[CSVOptions解析]
    B --> C{スキーマ指定?}
    C -->|Yes| D[ユーザースキーマ適用]
    C -->|No| E{inferSchema?}
    E -->|Yes| F[CSVInferSchema]
    E -->|No| G[全カラムString型]
    D --> H{header?}
    F --> H
    G --> H
    H -->|Yes| I[CSVHeaderChecker]
    H -->|No| J[UnivocityParser]
    I --> J
    J --> K{パースエラー?}
    K -->|PERMISSIVE| L[破損レコード格納]
    K -->|DROPMALFORMED| M[レコードスキップ]
    K -->|FAILFAST| N[例外スロー]
    K -->|No| O[DataFrame]
    L --> O
    M --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | パースモード | PERMISSIVE/DROPMALFORMED/FAILFASTの3モードで破損データを処理 | 読み込み時 |
| BR-26-02 | スキーマ推論 | inferSchema=trueで全データをスキャンして型を推論 | スキーマ未指定時 |
| BR-26-03 | ヘッダー検証 | header=trueでファイル先頭行をカラム名として使用 | 読み込み時 |
| BR-26-04 | デフォルトカラム | スキーマ未指定・ヘッダーなし時は_c0, _c1...の自動カラム名 | スキーマ・ヘッダー両方なし時 |

### 計算ロジック

CSVInferSchemaはデータ全体をスキャンし、各カラムの値から最も適切な型を推論する。型の優先順位: NullType → IntegerType → LongType → DoubleType → TimestampType → DateType → StringType。

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

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

本機能はファイルシステム上のCSVファイルを対象とし、直接的なデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MALFORMED_RECORD | パースエラー | CSV行のパースに失敗 | mode設定に応じた処理 |
| ENCODING_ERROR | エンコーディングエラー | 不正な文字エンコーディング | encoding設定の確認 |
| HEADER_MISMATCH | ヘッダーエラー | ヘッダー行とスキーマの不一致 | ヘッダー/スキーマの確認 |

### リトライ仕様

ファイル読み取りの失敗はタスクレベルでリトライされる。

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

書き出し時はFileOutputCommitterによるコミットプロトコルが適用される。

## パフォーマンス要件

- Univocityパーサーによる高速CSV解析
- スキーマ推論はデータ全体のスキャンが必要なためコストが高い
- カラムプルーニングによる不要カラムのスキップ

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

- ファイルシステムのアクセス権限に依存
- CSVインジェクション対策として適切な引用符・エスケープ処理

## 備考

- SparkのCSV解析にはUnivocityライブラリが使用されている
- multiLine=trueはパフォーマンスに影響する（パーティション分割が制限される）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CSVOptions.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala` | CSVオプション定義、パラメータ管理 |

**読解のコツ**: CSVOptionsはFileSourceOptionsを継承し、CaseInsensitiveMapでパラメータを管理する。34-39行目のコンストラクタで全パラメータを受け取る構造を理解する。

**主要処理フロー**:
- **34-39行目**: CSVOptionsクラス定義、parameters/columnPruning/defaultTimeZoneId/defaultColumnNameOfCorruptRecord
- **66-74行目**: equals()実装、パラメータ比較ロジック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CSVFileFormat.scala | `sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVFileFormat.scala` | FileFormatインターフェース実装 |

#### Step 3: パーサーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | UnivocityParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/UnivocityParser.scala` | CSV行の解析ロジック |
| 3-2 | CSVInferSchema.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVInferSchema.scala` | スキーマ推論ロジック |
| 3-3 | CSVHeaderChecker.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVHeaderChecker.scala` | ヘッダー行検証 |

#### Step 4: ジェネレーターを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | UnivocityGenerator.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/UnivocityGenerator.scala` | CSV行の生成ロジック |
| 4-2 | CSVExprUtils.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVExprUtils.scala` | CSV式ユーティリティ |

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

```
DataFrameReader.csv()
    │
    ├─ CSVFileFormat (V1)
    │      ├─ inferSchema() → CSVInferSchema
    │      ├─ prepareWrite()
    │      └─ buildReader()
    │             ├─ CSVOptions解析
    │             ├─ CSVHeaderChecker
    │             └─ UnivocityParser
    │                    └─ CsvParser (Univocityライブラリ)
    │
    └─ CSVDataSourceV2 (V2)
           └─ CSVScanBuilder → CSVPartitionReaderFactory
```

### データフロー図

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

CSVファイル ─────────▶ CSVOptions解析 ──────────▶ UnivocityParser
(テキスト)               │                           │
                        ├─ ヘッダー処理              ├─ 型変換
                        └─ スキーマ推論              └─ エラーハンドリング
                                                          │
                                                          ▼
                                                    DataFrame

DataFrame ──────────▶ UnivocityGenerator ────────▶ CSVファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CSVOptions.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala` | ソース | CSVオプション定義 |
| UnivocityParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/UnivocityParser.scala` | ソース | CSV解析エンジン |
| CSVInferSchema.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVInferSchema.scala` | ソース | スキーマ推論 |
| CSVHeaderChecker.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVHeaderChecker.scala` | ソース | ヘッダー検証 |
| UnivocityGenerator.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/UnivocityGenerator.scala` | ソース | CSV生成エンジン |
| CSVExprUtils.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVExprUtils.scala` | ソース | CSV式ユーティリティ |
