# 機能設計書 19-SQLパーサー

## 概要

本ドキュメントは、Apache Spark SQLのSQLパーサーについて、ANTLR4ベースのSQL文解析と論理プラン生成の設計仕様を記述した機能設計書である。

### 本機能の処理概要

SQL文字列をANTLR4パーサーで構文解析し、ASTBuilder（抽象構文木ビルダー）を通じてSpark CatalystのLogicalPlan（論理実行プラン）へ変換する。DDL/DML/クエリなど全てのSQL構文をサポートし、パラメータ置換やSQL Scripting等の拡張機能も提供する。

**業務上の目的・背景**：Spark SQLはSQL言語によるデータ処理のインターフェースを提供する。ユーザーが記述したSQL文を正しく解析し、内部の論理プラン表現へ変換することが、SQLクエリ実行の最初のステップである。構文エラーの適切な検出と報告も重要な役割。

**機能の利用シーン**：(1) spark.sql("SELECT ...")でのSQLクエリ実行、(2) CREATE TABLE等のDDL文実行、(3) DataFrame API内部でのSQL式パース、(4) テーブル識別子や関数識別子の解析、(5) パラメータ化クエリの実行。

**主要な処理内容**：
1. ParserInterfaceによる統一的なパースAPI提供（parsePlan, parseExpression等）
2. AbstractSqlParserでのANTLR4パーサー初期化とエラーハンドリング
3. AstBuilderによるANTLR4パースツリーからLogicalPlanへの変換
4. CatalystSqlParserによるカタログ操作のためのデータ型・式パース
5. SubstituteParamsParserによるパラメータ化クエリのサポート
6. SQL Scriptingのための複合文（CompoundPlanStatement）パース

**関連システム・外部連携**：ANTLR4ランタイム（パーサー生成基盤）、Catalyst Analyzer（論理プランの解析フェーズ）、SparkSession（SQLクエリ実行のエントリーポイント）

**権限による制御**：特になし（パースフェーズではアクセス権チェックは行わない）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | SQL Query Plans（SQL実行プラン） | 補助機能 | パース結果のLogicalPlanを可視化の基盤として使用 |

## 機能種別

SQL処理基盤 / 構文解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sqlText | String | Yes | 解析対象のSQL文字列 | 空でないこと |
| parameterContext | ParameterContext | No | パラメータ化クエリのコンテキスト | - |

### 入力データソース

ユーザーが記述したSQL文字列（SparkSession.sql()、DataFrame API等から入力）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| LogicalPlan | LogicalPlan | 論理実行プラン（parsePlan, parseQuery） |
| Expression | Expression | 式（parseExpression） |
| TableIdentifier | TableIdentifier | テーブル識別子（parseTableIdentifier） |
| FunctionIdentifier | FunctionIdentifier | 関数識別子（parseFunctionIdentifier） |
| Seq[String] | Seq[String] | マルチパート識別子（parseMultipartIdentifier） |
| StructType | StructType | テーブルスキーマ/ルーティンパラメータ（parseTableSchema, parseRoutineParam） |

### 出力先

Catalyst論理プランとして後続のAnalyzer、Optimizerフェーズに渡される。

## 処理フロー

### 処理シーケンス

```
1. パース要求の受信
   └─ ParserInterface.parsePlan(sqlText)等のAPI呼び出し
2. ANTLR4レキサー・パーサーの初期化
   └─ AbstractParser.parse()でSqlBaseParserを初期化
3. 構文解析
   └─ ANTLR4が文法ルールに基づいてパースツリーを生成
4. ASTビルド
   └─ AstBuilder.visitXxx()メソッドでパースツリーをLogicalPlanに変換
5. エラーハンドリング
   └─ StackOverflowErrorをキャッチしてparserStackOverflowエラーとして報告
6. CompoundStatement処理
   └─ SQL Scripting対応のための複合文処理
```

### フローチャート

```mermaid
flowchart TD
    A[SQL文字列入力] --> B[AbstractSqlParser.parsePlan]
    B --> C[parse関数呼び出し]
    C --> D[ANTLR4 Lexer/Parser生成]
    D --> E[parser.compoundOrSingleStatement]
    E --> F[ANTLR4パースツリー生成]
    F --> G[withErrorHandling]
    G --> H[AstBuilder.visitCompoundOrSingleStatement]
    H --> I{結果判定}
    I -->|CompoundPlanStatement| J[CompoundPlanStatement返却]
    I -->|LogicalPlan| K[LogicalPlan返却]
    I -->|その他| L[QueryParsingErrors.sqlStatementUnsupportedError]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | EOF付きパース | parseQuery()ではLEGACY_PARSE_QUERY_WITHOUT_EOF設定に基づきEOFを要求 | parseQuery呼び出し時 |
| BR-19-02 | StackOverflow保護 | パース中のStackOverflowErrorをキャッチしてparserStackOverflowエラーに変換 | 全パース処理 |
| BR-19-03 | パラメータ置換 | SubstituteParamsParserでパラメータ化クエリの置換を処理 | パラメータ付きクエリ時 |
| BR-19-04 | CompoundStatement分岐 | parsePlan()の結果がCompoundPlanStatementかLogicalPlanかで処理を分岐 | parsePlan呼び出し時 |
| BR-19-05 | Origin追跡 | パースツリーのコンテキストからOrigin（行番号・列番号）情報を追跡 | 全パース処理 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし（パースフェーズのみ） |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| PARSE_SYNTAX_ERROR | ParseException | SQL構文エラー | SparkParserErrorStrategyが構文エラーメッセージを生成 |
| PARSE_STACK_OVERFLOW | SparkThrowable | 深くネストされたSQL式 | StackOverflowErrorをキャッチしてユーザーフレンドリーなエラーに変換 |
| _LEGACY_ERROR_TEMP_0035 | ParseException | サポートされていないSQL文 | sqlStatementUnsupportedErrorを生成 |

### リトライ仕様

リトライは行わない。パースエラーはParseExceptionとして即座にユーザーに報告。

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

該当なし

## パフォーマンス要件

ANTLR4パーサーはSQL文字列のサイズに対してほぼ線形時間で処理を完了する。極端にネストが深い式ではStackOverflowの可能性がある。

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

パースフェーズではアクセス権チェックは行わない（後続のAnalyzerフェーズで実施）。SQLインジェクション対策としてパラメータ化クエリ（SubstituteParamsParser）を推奨。

## 備考

- CatalystSqlParserはカタログ操作（データ型パース、式パース）用の軽量パーサー
- SparkSqlParser（sql/core側）が実際のSparkSQL実行で使用されるメインパーサー
- ANTLR4の文法ファイルはSqlBaseLexer.g4, SqlBaseParser.g4で定義

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ParserInterface.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParserInterface.scala` | パーサーの公開API定義（parsePlan, parseExpression等） |
| 1-2 | DataTypeParserInterface.scala | `sql/api/src/main/scala/org/apache/spark/sql/catalyst/parser/DataTypeParserInterface.scala` | データ型パースのインターフェース |

**読解のコツ**: ParserInterfaceはDataTypeParserInterfaceを継承しており、データ型のパースも統合的に扱える。各メソッドは@throws[ParseException]アノテーション付き。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AbstractSqlParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AbstractSqlParser.scala` | ANTLR4パーサーの初期化とparse()メソッド |

**主要処理フロー**:
1. **33行目**: AbstractParser（ANTLR4初期化基盤）とParserInterfaceの両方を継承
2. **34行目**: astBuilder抽象メソッド（サブクラスでAstBuilder実装を指定）
3. **37-43行目**: parseExpression()でsingleExpressionルールをパースしAstBuilderで変換
4. **93-104行目**: parsePlan()でcompoundOrSingleStatementルールを使用
5. **113-122行目**: withErrorHandling()でStackOverflowErrorをキャッチ

#### Step 3: AST変換層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AstBuilder.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala` | ANTLR4ビジターパターンによるLogicalPlan生成 |

**読解のコツ**: AstBuilderは巨大なファイルであり、各visitXxxメソッドがANTLR4文法ルールに対応している。主要メソッドのみを追跡し、全体像を把握してから詳細に入るのがよい。

#### Step 4: エラーハンドリング層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SparkParserErrorStrategy.scala | `sql/api/src/main/scala/org/apache/spark/sql/catalyst/parser/SparkParserErrorStrategy.scala` | ANTLR4エラーリカバリ戦略のカスタマイズ |

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

```
SparkSession.sql(sqlText)
    │
    └─ ParserInterface.parsePlan(sqlText)
         │
         ├─ AbstractSqlParser.parsePlan(sqlText)
         │    └─ parse(sqlText) { parser =>
         │         ├─ ANTLR4 SqlBaseLexer (トークン化)
         │         ├─ ANTLR4 SqlBaseParser (構文解析)
         │         │    └─ parser.compoundOrSingleStatement()
         │         │         └─ ParseTree (ANTLR4パースツリー)
         │         │
         │         └─ withErrorHandling {
         │              └─ AstBuilder.visitCompoundOrSingleStatement()
         │                   ├─ visitQuery() → LogicalPlan
         │                   ├─ visitDDL() → LogicalPlan
         │                   └─ visitCompoundBody() → CompoundPlanStatement
         │              }
         │
         └─ SubstituteParamsParser (パラメータ化クエリ時)
              └─ パラメータ置換後にdelegateParsePlanを呼び出し
```

### データフロー図

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

SQL文字列        ───▶ ANTLR4 Lexer            ───▶ トークン列
                       └─ SqlBaseLexer

トークン列       ───▶ ANTLR4 Parser           ───▶ パースツリー
                       └─ SqlBaseParser

パースツリー     ───▶ AstBuilder              ───▶ LogicalPlan / Expression
                       └─ visitXxx()                (Catalyst内部表現)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ParserInterface.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParserInterface.scala` | ソース | パーサー公開API |
| AbstractSqlParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AbstractSqlParser.scala` | ソース | ANTLR4パーサー基盤 |
| AstBuilder.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala` | ソース | パースツリー→LogicalPlan変換 |
| CatalystSqlParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/CatalystSqlParser.scala` | ソース | Catalyst用軽量パーサー |
| SubstituteParamsParser.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/SubstituteParamsParser.scala` | ソース | パラメータ化クエリ対応 |
| ParameterContext.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParameterContext.scala` | ソース | パラメータコンテキスト |
| ParameterHandler.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParameterHandler.scala` | ソース | パラメータハンドラ |
| ParserUtils.scala | `sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/ParserUtils.scala` | ソース | パースユーティリティ |
| SparkParserErrorStrategy.scala | `sql/api/src/main/scala/org/apache/spark/sql/catalyst/parser/SparkParserErrorStrategy.scala` | ソース | エラーハンドリング戦略 |
| parsers.scala | `sql/api/src/main/scala/org/apache/spark/sql/catalyst/parser/parsers.scala` | ソース | AbstractParser基底クラス |
