# 機能設計書 6-SELECT文処理

## 概要

本ドキュメントは、SQLiteにおけるSELECT文の解析・実行・結果取得処理について、その設計と実装の詳細を記述する。SELECT文のパースから結果セットの生成までの一連の処理フローについて解説する。

### 本機能の処理概要

**業務上の目的・背景**：SELECT文はデータベースからデータを取得するための最も基本的かつ重要なSQL文である。単純な全件取得から、複雑なJOIN、サブクエリ、集約関数、ウィンドウ関数を含む高度なクエリまで、多様なデータ取得要件に対応する必要がある。

**機能の利用シーン**：
- データベースからのデータ取得（全件、条件付き、ソート付き）
- 複数テーブルの結合（JOIN）
- 集約処理（GROUP BY、集約関数）
- サブクエリを含む複雑なクエリ
- UNION、INTERSECT、EXCEPTによる集合演算
- ウィンドウ関数による高度な分析
- WASMデモでのSQL実行結果表示

**主要な処理内容**：
1. SELECT文のパースと構文木（Select構造体）の構築
2. FROM句の解析とテーブル参照の解決
3. WHERE句の解析と条件式の構築
4. GROUP BY句とHAVING句の処理
5. ORDER BY句とソート処理
6. LIMIT/OFFSET句の処理
7. VDBEコードの生成
8. 結果セットの構築と返却

**関連システム・外部連携**：
- パーサー（parse.y、tokenize.c）
- WHERE句最適化（where.c）
- VDBEコードジェネレータ（vdbe*.c）
- B-Treeストレージエンジン（btree.c）

**権限による制御**：sqlite3_set_authorizer()で設定されたauthorizerコールバックによるテーブル・カラムへのアクセス制御が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 基本デモ（UIスレッド版） | 主画面 | db.exec()でのSELECT文実行とコールバック処理 |
| 4 | 基本デモ（Worker版） | 主画面 | Worker内でのSQL実行処理 |
| 5 | JS Storage デモ | 補助画面 | 永続化DBへのクエリ実行 |
| 8 | SQLite3 Fiddle | 主画面 | SQLクエリ実行と結果表示 |
| 12 | Tester1（メインスレッド版） | 主画面 | 各種SELECT文の単体・回帰テスト |
| 18 | SQLTester | 主画面 | テストスクリプト内SELECT文実行 |

## 機能種別

データ取得処理（CRUD操作のRead）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SELECT句 | ExprList* | Yes | 取得するカラム・式のリスト | *（アスタリスク）で全カラム |
| FROM句 | SrcList* | No | 参照するテーブルのリスト | 省略可（定数式のみの場合） |
| WHERE句 | Expr* | No | 抽出条件 | 省略可 |
| GROUP BY句 | ExprList* | No | グループ化カラム | 省略可 |
| HAVING句 | Expr* | No | グループ化後の条件 | GROUP BY必須 |
| ORDER BY句 | ExprList* | No | ソートカラム | 省略可 |
| LIMIT句 | Expr* | No | 取得件数制限 | 省略可 |
| OFFSET句 | Expr* | No | 開始位置オフセット | LIMIT必須 |

### 入力データソース

- データベーステーブル
- インデックス
- ビュー定義
- 仮想テーブル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 結果セット | sqlite3_stmt* | 行のコレクション |
| カラム数 | int | 結果セットのカラム数 |
| カラム名 | const char* | 各カラムの名前 |
| カラム値 | sqlite3_value* | 各セルの値 |

### 出力先

- プリペアドステートメント経由でアプリケーションへ
- コールバック関数への行単位配信（sqlite3_exec使用時）

## 処理フロー

### 処理シーケンス

```
1. SELECT文のパース
   └─ Select構造体の構築（sqlite3SelectNew()）

2. FROM句の処理
   ├─ テーブル参照の解決
   ├─ JOIN条件の解析
   └─ サブクエリの再帰処理

3. WHERE句の最適化
   ├─ whereExprAnalyze()で式を分析
   ├─ インデックス選択（where.c）
   └─ 最適なスキャン方法の決定

4. SELECT句の処理
   ├─ 式のコード生成
   ├─ 集約関数の識別
   └─ DISTINCT処理の準備

5. GROUP BY処理
   ├─ ソーターの準備
   └─ 集約関数の処理

6. ORDER BY処理
   ├─ ソート順の決定
   └─ ソーターコードの生成

7. VDBEコード生成
   ├─ ループ構造の生成
   ├─ 結果行の構築
   └─ LIMIT/OFFSET処理

8. 実行と結果返却
   └─ sqlite3_step()で行を取得
```

### フローチャート

```mermaid
flowchart TD
    A[SELECT文入力] --> B[sqlite3SelectNew]
    B --> C[FROM句解析]
    C --> D{JOIN あり?}
    D -->|Yes| E[JOIN条件処理]
    D -->|No| F[WHERE句最適化]
    E --> F
    F --> G[インデックス選択]
    G --> H{GROUP BY?}
    H -->|Yes| I[集約処理準備]
    H -->|No| J[単純SELECT]
    I --> K[HAVING処理]
    K --> L[ORDER BY処理]
    J --> L
    L --> M[VDBEコード生成]
    M --> N[sqlite3_step実行]
    N --> O[結果行返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | カラム参照解決 | 曖昧なカラム参照はエラー、テーブル名で修飾して解決 | 複数テーブルJOIN時 |
| BR-002 | GROUP BY制約 | 集約関数以外の式はGROUP BYに含まれる必要あり | GROUP BY使用時 |
| BR-003 | HAVING制約 | HAVINGはGROUP BY後に評価される | GROUP BY使用時 |
| BR-004 | ORDER BY位置 | ORDER BYはSELECT結果に対して適用 | 常時 |
| BR-005 | NULL処理 | NULLは比較演算でFALSE相当、ORDER BYで最後 | 常時 |
| BR-006 | DISTINCT処理 | 重複行を除去して返却 | DISTINCT指定時 |

### 計算ロジック

**集約関数の計算**：
- COUNT(*): 行数をカウント
- SUM(x): xの合計
- AVG(x): xの平均（SUM/COUNT）
- MIN(x): xの最小値
- MAX(x): xの最大値

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| SELECT | 指定テーブル | SELECT | データの読み取り |

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

SELECT文はデータを変更しないため、読み取り操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_ERROR | 構文エラー | 不正なSQL構文 | SQLを修正 |
| SQLITE_ERROR | カラム不明 | 存在しないカラム参照 | カラム名を確認 |
| SQLITE_ERROR | 曖昧な参照 | 複数テーブルに同名カラム | テーブル名で修飾 |
| SQLITE_NOMEM | メモリ不足 | 結果セット構築時 | メモリを解放して再試行 |
| SQLITE_BUSY | ロック競合 | 他接続がテーブルをロック中 | リトライまたはタイムアウト設定 |

### リトライ仕様

- SQLITE_BUSYは設定されたビジーハンドラに従ってリトライ
- メモリ不足は環境改善後に再試行

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

- SELECT文は暗黙の読み取りトランザクション内で実行
- 明示的トランザクション内でも実行可能
- 読み取り中に他の接続からの変更は分離レベルに依存

## パフォーマンス要件

- インデックス使用時はO(log n)のアクセス
- フルスキャン時はO(n)
- WHERE句最適化により適切なインデックスを自動選択
- EXPLAIN QUERYPLANで実行計画を確認可能

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

- authorizerコールバックによるアクセス制御
- プリペアドステートメントによるSQLインジェクション防止
- ビューによるデータアクセスの抽象化

## 備考

- 複雑なクエリは内部で複数のパスに分割される場合がある
- CTEはWITH句で定義し、再帰CTEもサポート
- ウィンドウ関数はSQL:2003標準に準拠

---

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

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

### 推奨読解順序

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

まず、SELECT文を表す構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | Select構造体、SrcList構造体、ExprList構造体の定義 |
| 1-2 | select.c | `src/select.c` | DistinctCtx、SortCtx構造体の定義 |

**読解のコツ**: Select構造体はSELECT文全体を表し、pEList（SELECT句）、pSrc（FROM句）、pWhere（WHERE句）等のフィールドを持つ。

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

SELECT文処理の起点を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.c | `src/select.c` | sqlite3Select()関数 |

**主要処理フロー**:
1. **126-178行目**: sqlite3SelectNew()でSelect構造体を構築
2. SELECT文の各要素（pEList、pSrc、pWhere等）を設定
3. メモリ割り当て失敗時のクリーンアップ

#### Step 3: FROM句処理を理解する

テーブル参照とJOIN処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.c | `src/select.c` | sqlite3JoinType()でJOINタイプ判定 |

**主要処理フロー**:
- **262-300行目**: sqlite3JoinType()でJOINキーワードの解析
- JT_INNER、JT_LEFT、JT_RIGHT、JT_CROSS等のフラグ設定

#### Step 4: 結果構築を理解する

VDBEコード生成と結果セット構築を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | select.c | `src/select.c` | selectInnerLoop()で結果行を構築 |
| 4-2 | select.c | `src/select.c` | generateSortTail()でソート処理 |

**主要処理フロー**:
- 結果カラムの式をコード生成
- DISTINCT処理（エフェメラルテーブル使用）
- ORDER BY処理（ソーター使用）

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

```
sqlite3Select()                    [select.c]
    │
    ├─ sqlite3SelectExpand()       名前解決・展開
    │
    ├─ sqlite3WhereBegin()         [where.c]
    │      └─ WHERE句最適化・インデックス選択
    │
    ├─ selectInnerLoop()           結果行構築
    │      ├─ 式のコード生成
    │      └─ DISTINCT処理
    │
    ├─ sqlite3WhereEnd()           ループ終了処理
    │
    └─ generateSortTail()          ORDER BY処理
           └─ ソート結果出力
```

### データフロー図

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

SELECT文          ───▶ sqlite3SelectNew()        ───▶ Select構造体
                           │
テーブルデータ    ───▶ sqlite3Select()          ───▶ 結果セット
                           │
                           ├─▶ WHERE最適化
                           ├─▶ インデックススキャン
                           ├─▶ 結果行構築
                           └─▶ ソート処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.c | `src/select.c` | ソース | SELECT文処理のメイン実装 |
| where.c | `src/where.c` | ソース | WHERE句最適化 |
| whereexpr.c | `src/whereexpr.c` | ソース | WHERE式の分析 |
| wherecode.c | `src/wherecode.c` | ソース | WHERE用VDBEコード生成 |
| expr.c | `src/expr.c` | ソース | 式の処理 |
| resolve.c | `src/resolve.c` | ソース | 名前解決 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダー | Select構造体等の定義 |
