# 機能設計書 43-クエリ式

## 概要

本ドキュメントは、F#のクエリ式（Query Expressions）機能の設計を記述する。

### 本機能の処理概要

クエリ式は、F#においてSQLライクな構文でデータクエリを記述するためのコンピュテーション式である。QueryBuilderクラスを通じて、データベースクエリやコレクション操作を宣言的に表現できる。

**業務上の目的・背景**：データベースクエリやコレクション操作を、SQLに近い直感的な構文で記述可能にすることで、開発者の生産性を向上させる。C#のLINQクエリ構文に相当する機能をF#で提供し、データ指向のプログラミングを支援する。

**機能の利用シーン**：
- データベースからのデータ取得・検索
- メモリ上のコレクションに対するクエリ操作
- 複数データソースの結合（JOIN）
- データの集計・グループ化

**主要な処理内容**：
1. query { } コンピュテーション式の解析
2. QueryBuilderメソッドへの変換
3. クエリ演算子の適用（select, where, join等）
4. IQueryable/IEnumerableとしての実行
5. 結果の型変換と返却

**関連システム・外部連携**：System.Linq.IQueryable、LINQプロバイダー、F# Quotations

**権限による制御**：特になし（純粋なライブラリ機能）

## 関連画面

本機能はコアライブラリ機能のため、直接関連する画面はない。

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

## 機能種別

データクエリ / コンピュテーション式

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | IQueryable<'T> / IEnumerable<'T> | Yes | クエリ対象のデータソース | null不可 |
| selector | 'T -> 'U | No | 選択・射影関数 | - |
| predicate | 'T -> bool | No | フィルタ条件 | - |
| keySelector | 'T -> 'Key | No | キー選択関数 | - |

### 入力データソース

- IQueryable<'T>: データベースなどの外部データソース
- IEnumerable<'T>: メモリ上のコレクション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| クエリ結果 | seq<'T> / 'T | クエリ実行結果 |

### 出力先

メモリ上のシーケンスまたは単一値

## 処理フロー

### 処理シーケンス

```
1. query { } 式の解析
   └─ コンパイラがコンピュテーション式として解釈
2. QueryBuilderメソッドへの変換
   └─ for → For, select → Select, where → Where 等
3. クエリ式ツリーの構築
   └─ Quoteメソッドで式ツリーを取得
4. クエリの実行
   └─ Run/RunQueryAsQueryable/RunQueryAsEnumerableで実行
5. 結果の返却
   └─ 遅延評価シーケンスまたは即時評価結果
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[query { } 式を解析]
    B --> C[QueryBuilderメソッドに変換]
    C --> D{データソースの種類}
    D -->|IQueryable| E[式ツリーを構築]
    D -->|IEnumerable| F[直接評価]
    E --> G[RunQueryAsQueryableで実行]
    F --> H[RunQueryAsEnumerableで実行]
    G --> I[結果を返却]
    H --> I
    I --> J[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 遅延評価 | クエリは実際に結果が必要になるまで実行しない | すべてのクエリ |
| BR-02 | 型推論 | select句の戻り値型は自動推論 | select使用時 |
| BR-03 | ソート順序 | sortBy後のthenByで複合ソート可能 | ソート操作 |

### 計算ロジック

主要なクエリ演算子:
- `for ... in ... do`: データソースからの列挙
- `select`: 射影（値の変換）
- `where`: フィルタリング
- `sortBy`/`sortByDescending`: ソート
- `thenBy`/`thenByDescending`: 二次ソート
- `groupBy`: グループ化
- `join`: 内部結合
- `leftOuterJoin`: 左外部結合
- `distinct`: 重複排除
- `take`/`skip`: ページング
- `head`/`last`: 先頭/末尾要素
- `count`: 件数カウント
- `sumBy`/`averageBy`: 集計
- `minBy`/`maxBy`: 最小/最大値

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

LINQプロバイダー経由でデータベース操作を実行。本機能自体はSQLを直接発行しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvalidOperationException | 実行時エラー | 空シーケンスでhead/exactlyOne | OrDefault版を使用 |
| NotSupportedException | 実行時エラー | プロバイダー非サポート演算子 | クライアント評価に変更 |
| ArgumentNullException | 実行時エラー | nullソース | nullチェックを追加 |

### リトライ仕様

該当なし

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

該当なし（トランザクション管理はLINQプロバイダーが担当）

## パフォーマンス要件

- クエリは遅延評価され、必要時にのみ実行
- IQueryableの場合、可能な限りデータベースサイドで処理
- ネストされたクエリの最適化（EliminateNestedQueries）

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

- クエリのパラメータはLINQプロバイダーによりエスケープ
- ユーザー入力を直接クエリに含めないこと

## 備考

query { }はF#のコンピュテーション式構文を使用しており、QueryBuilderクラスのメソッドに展開される。

---

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

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

### 推奨読解順序

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

クエリ式の基盤となるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Query.fs | `src/FSharp.Core/Query.fs` | QuerySource<'T, 'Q>型（18-20行目）でクエリソースの構造を把握 |
| 1-2 | Query.fs | `src/FSharp.Core/Query.fs` | ForwardDeclarations.IQueryMethods（40-42行目）でインターフェースを確認 |

**読解のコツ**: QuerySource<'T, 'Q>は要素型'Tとクエリの種類'Q（IQueryableまたはIEnumerable）を保持するラッパー型。

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

QueryBuilderクラスがコンピュテーション式のエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Query.fs | `src/FSharp.Core/Query.fs` | QueryBuilder型（51-262行目）でビルダーメソッドを確認 |
| 2-2 | Query.fs | `src/FSharp.Core/Query.fs` | Runメソッド（251-262行目）でクエリ実行を理解 |

**主要処理フロー**:
1. **52-53行目**: Forメソッドでシーケンスの列挙
2. **77-81行目**: Select/Whereメソッドで射影・フィルタ
3. **251-262行目**: Run/RunQueryAsQueryableで実行

#### Step 3: クエリ演算子を理解する

各クエリ演算子の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Query.fs | `src/FSharp.Core/Query.fs` | ソート演算子（215-237行目）SortBy/ThenBy |
| 3-2 | Query.fs | `src/FSharp.Core/Query.fs` | 集計演算子（131-211行目）SumBy/AverageBy |
| 3-3 | Query.fs | `src/FSharp.Core/Query.fs` | 結合演算子（242-249行目）Join/GroupJoin/LeftOuterJoin |

#### Step 4: クエリ変換処理を理解する

式ツリーの変換と最適化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Query.fs | `src/FSharp.Core/Query.fs` | Queryモジュール（302行目以降）で変換関数群 |
| 4-2 | Query.fs | `src/FSharp.Core/Query.fs` | MakeSelect/MakeWhere等のMake*関数でLINQ式生成 |

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

```
query { } コンピュテーション式
    │
    ├─ QueryBuilder (コンピュテーション式ビルダー)
    │      ├─ For (シーケンス列挙)
    │      ├─ Select (射影)
    │      ├─ Where (フィルタ)
    │      ├─ SortBy/ThenBy (ソート)
    │      ├─ GroupBy/GroupValBy (グループ化)
    │      ├─ Join/LeftOuterJoin (結合)
    │      ├─ Take/Skip (ページング)
    │      ├─ SumBy/AverageBy/MinBy/MaxBy (集計)
    │      └─ Run (実行)
    │             ├─ RunQueryAsQueryable (IQueryable用)
    │             │      └─ ForwardDeclarations.Query.Execute
    │             └─ RunQueryAsEnumerable (IEnumerable用)
    │                    └─ EvaluateQuotation
    │
    └─ Query モジュール (変換・実行)
           ├─ MakeSelect/MakeWhere/MakeOrderBy... (式生成)
           ├─ CallFirst/CallLast/CallCount... (実行)
           └─ RewriteExpr/EliminateNestedQueries (最適化)
```

### データフロー図

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

query { }式      ───▶  QueryBuilder        ───▶  QuerySource
  コード                  (式構築)                 (クエリ定義)
    │
    ▼
データソース     ───▶  Query.Make*         ───▶  LINQ Expression
  IQueryable            (式変換)                 (クエリ式ツリー)
    │
    ▼
                ───▶  Query.Call* / Run   ───▶  クエリ結果
                      (実行)                     seq<'T>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Query.fs | `src/FSharp.Core/Query.fs` | ソース | クエリ式の主要実装 |
| Linq.fs | `src/FSharp.Core/Linq.fs` | ソース | LINQ統合サポート |
| quotations.fs | `src/FSharp.Core/quotations.fs` | ソース | F#式ツリー |
