# 機能設計書 5-SQLパーサー/トークナイザー

## 概要

本ドキュメントは、SQLiteにおけるSQL文字列の字句解析（トークナイザー）と構文解析（パーサー）機能について、その設計と実装の詳細を記述する。SQL文字列を個別のトークンに分割し、文法規則に基づいて解析木を構築する処理について解説する。

### 本機能の処理概要

**業務上の目的・背景**：SQLiteがSQL文を実行するためには、まず入力されたSQL文字列を解析して内部表現に変換する必要がある。トークナイザーは文字列を意味のある最小単位（トークン）に分割し、パーサーは文法規則に従ってこれらのトークンを解析して抽象構文木を構築する。この処理はSQL実行の最初のステップであり、全てのSQL操作の基盤となる。

**機能の利用シーン**：
- sqlite3_prepare()、sqlite3_exec()などでSQL文が渡された時
- ユーザー入力のSQL文を解析する場面（SQLite3 Fiddle等）
- DDL/DML文の解析と実行
- テストスクリプトのSQL解析（SQLTester）

**主要な処理内容**：
1. SQL文字列の字句解析（トークン分割）
2. キーワード認識とトークンタイプの判定
3. Lemonパーサージェネレータで生成されたパーサーによる構文解析
4. 抽象構文木（AST）の構築
5. 構文エラーの検出と報告

**関連システム・外部連携**：
- Lemonパーサージェネレータ（tool/lemon.c）
- VDBEコードジェネレータ（各種SQL文処理モジュール）

**権限による制御**：パーサー自体には権限制御はないが、解析結果に対してauthorizer callback（sqlite3_set_authorizer）が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | SQLite3 Fiddle | 主画面 | ユーザー入力SQLの解析処理 |
| 18 | SQLTester | 主画面 | 外部テストスクリプトの解析・実行 |
| 21 | Lemon パーサージェネレータ | 主画面 | Lemonパーサージェネレータのドキュメント表示 |

## 機能種別

解析処理（SQL文字列からの内部表現への変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| zSql | const char* | Yes | 解析対象のSQL文字列（UTF-8） | NULL不可 |

### 入力データソース

- アプリケーションから渡されるSQL文字列
- データベースに格納されたスキーマ定義SQL（sqlite_schema）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| トークン列 | Token構造体の配列 | 字句解析結果 |
| 解析木 | Parse構造体 | 構文解析結果、VDBEコード生成用の中間表現 |
| エラー情報 | char* | 構文エラー時のエラーメッセージ |

### 出力先

- Parse構造体（内部データ構造）
- エラー時はsqlite3_errmsg()で取得可能

## 処理フロー

### 処理シーケンス

```
1. トークナイザー初期化
   └─ 入力SQL文字列の先頭から解析開始

2. トークン抽出ループ
   ├─ 文字クラスの判定（aiClass配列参照）
   ├─ トークンタイプの決定
   │   ├─ キーワード：keywordhash.hでハッシュ検索
   │   ├─ 識別子：TK_ID
   │   ├─ 数値リテラル：TK_INTEGER、TK_FLOAT
   │   ├─ 文字列リテラル：TK_STRING
   │   ├─ 演算子：TK_PLUS、TK_MINUS等
   │   └─ コメント：TK_COMMENT（スキップ）
   └─ トークンをパーサーに渡す

3. パーサー処理
   ├─ sqlite3Parser()でトークンを受け取る
   ├─ 文法規則に従ってリダクション
   ├─ アクションコードの実行
   └─ 構文木の構築

4. 解析完了
   ├─ 成功：Parse構造体に解析結果
   └─ 失敗：エラーメッセージの設定
```

### フローチャート

```mermaid
flowchart TD
    A[SQL文字列入力] --> B[sqlite3GetToken]
    B --> C{トークン種別}
    C -->|キーワード| D[キーワードハッシュ検索]
    C -->|識別子| E[TK_ID]
    C -->|数値| F[TK_INTEGER/FLOAT]
    C -->|文字列| G[TK_STRING]
    C -->|演算子| H[演算子トークン]
    C -->|コメント| I[スキップ]
    D --> J[sqlite3Parser]
    E --> J
    F --> J
    G --> J
    H --> J
    I --> B
    J --> K{文法規則適用}
    K -->|成功| L[構文木構築]
    K -->|失敗| M[構文エラー]
    L --> N{入力終了?}
    N -->|No| B
    N -->|Yes| O[解析完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | キーワード大文字小文字非区別 | SQLキーワードは大文字小文字を区別しない | 常時 |
| BR-002 | 識別子のクォート | "..."、[...]、`...`で囲むとキーワードを識別子として使用可能 | 常時 |
| BR-003 | コメントスキップ | --（行コメント）と/* */（ブロックコメント）はスキップ | 常時 |
| BR-004 | UTF-8対応 | 識別子にUTF-8文字を使用可能 | 常時 |
| BR-005 | 数値セパレータ | アンダースコア(_)を数値内のセパレータとして使用可能 | SQLITE_DIGIT_SEPARATOR定義時 |

### 計算ロジック

**キーワードハッシュ計算**：
- mkkeywordhash.cで生成されたハッシュテーブル（keywordhash.h）を使用
- 高速なキーワード検索を実現

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

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

本機能自体はデータベース操作を行わない（解析処理のみ）。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_ERROR | 構文エラー | 不正なSQL文法 | エラーメッセージを確認してSQLを修正 |
| SQLITE_NOMEM | メモリ不足 | 解析木構築時のメモリ確保失敗 | メモリを解放して再試行 |
| SQLITE_TOOBIG | 入力過大 | SQL文が長すぎる | SQL文を分割 |

### リトライ仕様

構文エラーはSQL文の修正が必要。メモリ不足は環境改善後に再試行可能。

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

本機能はトランザクション処理を伴わない（解析フェーズのみ）。

## パフォーマンス要件

- トークン化は1文字あたり数十ナノ秒程度
- キーワードハッシュ検索はO(1)
- 全体の解析時間はSQL文の長さにほぼ比例

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

- パーサー自体にSQLインジェクション対策はない（上位層で対応）
- 不正な入力によるバッファオーバーフロー対策はコード内で実施
- 極端に長いSQL文によるDoS攻撃への対策として長さ制限あり

## 備考

- パーサーはLemonパーサージェネレータ（LALR(1)）で自動生成
- parse.yが文法定義ファイル、parse.cが生成されたパーサー
- キーワードハッシュはmkkeywordhash.cで生成

---

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

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

### 推奨読解順序

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

まず、トークンと解析結果を表す構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sqliteInt.h | `src/sqliteInt.h` | Token構造体、Parse構造体の定義 |
| 1-2 | parse.h | `src/parse.h` | トークンタイプ定数（TK_*）の定義 |

**読解のコツ**: Token構造体はトークンの位置と長さを保持。Parse構造体は解析状態と結果を保持し、後続のコード生成で使用される。

#### Step 2: トークナイザーを理解する

字句解析の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tokenize.c | `src/tokenize.c` | sqlite3GetToken()の実装 |

**主要処理フロー**:
1. **21-60行目**: 文字クラス定義（CC_SPACE、CC_DIGIT等）
2. **61-100行目**: aiClass配列（文字から文字クラスへのマッピング）
3. **273-500行目**: sqlite3GetToken()関数本体、switch文によるトークン判定
4. **279-288行目**: 空白文字の処理（TK_SPACE）
5. **289-300行目**: マイナス記号とコメントの処理
6. **433-498行目**: 数値リテラルの処理（整数、浮動小数点、16進数）

#### Step 3: キーワード認識を理解する

SQLキーワードの認識処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | keywordhash.h | `src/keywordhash.h` | キーワードハッシュテーブル（自動生成） |
| 3-2 | tokenize.c | `src/tokenize.c` | sqlite3KeywordCode()の呼び出し |

**主要処理フロー**:
- **137-148行目**: keywordhash.hのインクルードと説明コメント

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

構文解析の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parse.y | `src/parse.y` | 文法定義（Lemon形式） |
| 4-2 | parse.c | `src/parse.c` | 自動生成されたパーサー |
| 4-3 | tokenize.c | `src/tokenize.c` | sqlite3RunParser()でパーサー呼び出し |

**主要処理フロー**:
- parse.yの文法規則がparse.cにコンパイルされる
- sqlite3Parser()が各トークンを受け取り、リダクションを実行

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

```
sqlite3_prepare_v2()               [prepare.c]
    │
    └─ sqlite3RunParser()          [tokenize.c]
           │
           ├─ sqlite3GetToken()    [tokenize.c:273]
           │      │
           │      ├─ 文字クラス判定  [aiClass配列]
           │      │
           │      └─ キーワード検索  [keywordhash.h]
           │             └─ sqlite3KeywordCode()
           │
           └─ sqlite3Parser()      [parse.c]
                  │
                  ├─ sqlite3ParserInit()
                  │
                  ├─ 文法規則適用（ループ）
                  │      │
                  │      └─ アクションコード実行
                  │             └─ 構文木構築
                  │
                  └─ sqlite3ParserFinalize()
```

### データフロー図

```
[入力]                    [トークナイザー]              [パーサー]                [出力]

SQL文字列    ───▶ sqlite3GetToken()    ───▶ sqlite3Parser()    ───▶ Parse構造体
"SELECT..."           │                           │                      │
                      ▼                           ▼                      ▼
                 Token列                     文法規則適用           構文木/エラー
                 [TK_SELECT]                    │
                 [TK_STAR]                      ▼
                 [TK_FROM]                 アクション実行
                 [TK_ID]                       │
                 ...                           ▼
                                          Select構造体等
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tokenize.c | `src/tokenize.c` | ソース | トークナイザー実装、パーサー呼び出し |
| parse.y | `src/parse.y` | 文法定義 | SQL文法のLemon形式定義 |
| parse.c | `src/parse.c` | ソース | Lemonで自動生成されたパーサー |
| parse.h | `src/parse.h` | ヘッダー | トークンタイプ定数定義 |
| keywordhash.h | `src/keywordhash.h` | ヘッダー | キーワードハッシュテーブル |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダー | Token、Parse構造体定義 |
| tool/lemon.c | `tool/lemon.c` | ツール | パーサージェネレータ |
| tool/mkkeywordhash.c | `tool/mkkeywordhash.c` | ツール | キーワードハッシュ生成 |
