# 機能設計書 82-Spark Connect JDBCクライアント

## 概要

本ドキュメントは、JDBC標準インターフェース経由でSpark Connectサーバーに接続するドライバーの機能設計を記述する。

### 本機能の処理概要

Spark Connect JDBCクライアントは、標準的なJDBC（Java Database Connectivity）インターフェースを実装したドライバーであり、既存のJDBCアプリケーションやBIツールからSpark Connectサーバーに透過的に接続し、SQLクエリを実行することを可能にする。

**業務上の目的・背景**：多くの企業がJDBCベースのBIツール（Tableau、PowerBI等）やデータ分析ツールを使用している。Spark Connect JDBCクライアントは、これらのツールからSpark Connectサーバーに標準JDBC接続を提供することで、既存のツールチェーンを変更することなくSparkの分散データ処理能力を活用できるようにする。JDBC標準に準拠することで、アプリケーションの移植性と互換性を確保する。

**機能の利用シーン**：BIツールからのSparkデータソースへの接続、既存JDBCアプリケーションからのSpark SQL実行、データベースマイグレーションツールからのスキーマ操作、JDBCベースのETLツールとの連携。

**主要な処理内容**：
1. JDBCドライバー登録：DriverManagerへの自動登録（static初期化ブロック）
2. 接続確立：jdbc:sc://形式のURLを解析しSparkConnectClientを構築
3. SQL実行：StatementインターフェースでSQLをSparkSessionに送信
4. 結果セット処理：SparkのDataFrameをJDBC ResultSetとして返却
5. メタデータ取得：DatabaseMetaDataインターフェースでカタログ情報を提供

**関連システム・外部連携**：Spark Connectサーバー（gRPC）、JDBCクライアントアプリケーション、BIツール

**権限による制御**：JDBC接続プロパティで認証情報を伝達し、Spark Connectサーバー側の認証・認可機構で権限制御が行われる

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はJDBCドライバーであり直接関連する画面はない |

## 機能種別

データ連携 / API通信

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | String | Yes | JDBC接続URL（jdbc:sc://host:port形式） | jdbc:sc://プレフィックス必須、null不可 |
| info | Properties | No | 接続プロパティ（認証情報等） | - |
| catalog | String | No | デフォルトカタログ名 | - |
| schema | String | No | デフォルトスキーマ名 | - |

### 入力データソース

JDBCクライアントアプリケーションからのSQL文字列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Connection | java.sql.Connection | JDBC接続オブジェクト |
| ResultSet | java.sql.ResultSet | SQL実行結果セット |
| ResultSetMetaData | java.sql.ResultSetMetaData | 結果セットのメタデータ（カラム名・型等） |
| DatabaseMetaData | java.sql.DatabaseMetaData | データベースメタデータ |

### 出力先

JDBCクライアントアプリケーション

## 処理フロー

### 処理シーケンス

```
1. ドライバー登録
   └─ SparkConnectDriver staticブロックでDriverManager.registerDriver()
2. 接続確立
   └─ acceptsURL("jdbc:sc://...")でURL検証、SparkConnectConnection生成
3. SparkConnectClient構築
   └─ URL（jdbc:プレフィックス除去）からgRPCクライアントを構築
4. SparkSession生成
   └─ SparkSession.builder().client(client).create()
5. SQL実行
   └─ SparkConnectStatement.execute()でSparkSession.sql()を呼び出し
6. 結果取得
   └─ DataFrameをSparkConnectResultSetにラップして返却
7. 接続クローズ
   └─ SparkSession.close()でリソース解放
```

### フローチャート

```mermaid
flowchart TD
    A[DriverManager.getConnection] --> B{URL検証}
    B -->|jdbc:sc://| C[SparkConnectConnection生成]
    B -->|その他| D[null返却]
    C --> E[SparkConnectClient構築]
    E --> F[SparkSession生成]
    F --> G[Statement作成]
    G --> H[SQL実行]
    H --> I[DataFrame取得]
    I --> J[ResultSetラップ]
    J --> K[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-82-01 | URL検証 | jdbc:sc://で始まるURLのみ受け付ける | connect()呼び出し時 |
| BR-82-02 | null URL拒否 | URLがnullの場合SQLExceptionをスロー | connect()呼び出し時 |
| BR-82-03 | 接続状態管理 | closedフラグで接続状態を管理し、閉じた接続での操作はSQLExceptionをスロー | 各JDBC操作時 |
| BR-82-04 | セッション有効性 | client.isSessionValid()でセッション有効性を検証する | 各JDBC操作時 |

### 計算ロジック

バージョン情報はSPARK_VERSIONからVersionUtilsを使ってメジャー/マイナーバージョンを抽出する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| executeQuery | 任意 | SELECT | JDBCクエリをSpark SQLとして実行 |
| execute | 任意 | DDL/DML | 任意のSQL文をSpark SQLとして実行 |
| setCatalog | カタログ | 設定変更 | アクティブカタログの切り替え |
| setSchema | スキーマ | 設定変更 | アクティブスキーマ（データベース）の切り替え |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLException | JDBC接続エラー | URLがnullの場合 | 正しいURLを指定する |
| SQLException | セッション無効 | Spark Connectセッションが無効な場合 | 再接続する |
| SQLFeatureNotSupportedException | 未サポート | getParentLogger等の未実装メソッド呼び出し | サポートされるメソッドを使用する |

### リトライ仕様

JDBC層でのリトライは行わない。下位のSparkConnectClientのリトライ機構に委譲する。

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

JDBC Connectionのauto-commit設定はサポートされるが、明示的なトランザクション制御（BEGIN/COMMIT/ROLLBACK）はSpark SQLの仕様に依存する。

## パフォーマンス要件

- 接続確立時にgRPCチャネルを1回構築し、以降の操作で再利用する
- ResultSetは遅延評価でデータを取得し、大量データの一括ロードを回避する

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

- JDBC接続プロパティで認証トークンを伝達可能
- gRPC通信のセキュリティはSparkConnectClient側の設定に依存する
- jdbcCompliant()はfalseを返す（完全なJDBC準拠ではない）

## 備考

本ドライバーはJDBC標準の完全な実装ではなく、Spark SQLでサポートされる操作のサブセットを提供する。BIツールとの互換性はツールごとに検証が必要。

---

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

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

### 推奨読解順序

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

JDBCインターフェースの実装構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NonRegisteringSparkConnectDriver.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/NonRegisteringSparkConnectDriver.scala` | **27-49行目**: Driverインターフェース実装、acceptsURL("jdbc:sc://")のURL検証ロジック |
| 1-2 | SparkConnectConnection.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectConnection.scala` | **29-80行目**: Connection実装、SparkConnectClientとSparkSessionの保持 |

**読解のコツ**: JDBCの標準インターフェース（Driver, Connection, Statement, ResultSet）を順に実装している。各クラスはSpark Connect固有のオブジェクトを内部に保持する。

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

ドライバー登録と接続確立の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SparkConnectDriver.java | `sql/connect/client/jdbc/src/main/java/org/apache/spark/sql/connect/client/jdbc/SparkConnectDriver.java` | **23-31行目**: staticブロックでDriverManager.registerDriver()を呼び出し自動登録 |

**主要処理フロー**:
1. **24-28行目**: staticブロックでDriverManagerにドライバーを登録
2. **29行目** (NonRegisteringSparkConnectDriver): acceptsURLで"jdbc:sc://"プレフィックスを確認
3. **31-36行目** (NonRegisteringSparkConnectDriver): URL検証後SparkConnectConnectionを生成

#### Step 3: SQL実行フローを理解する

SQL文の実行とResultSet返却の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SparkConnectStatement.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectStatement.scala` | Statement実装、SparkSession.sql()呼び出し |
| 3-2 | SparkConnectResultSet.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectResultSet.scala` | ResultSet実装、DataFrameのイテレーション |
| 3-3 | SparkConnectResultSetMetaData.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectResultSetMetaData.scala` | ResultSetMetaData実装 |
| 3-4 | SparkConnectDatabaseMetaData.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectDatabaseMetaData.scala` | DatabaseMetaData実装、カタログ情報取得 |

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

```
DriverManager.getConnection("jdbc:sc://host:port")
    |
    +-- SparkConnectDriver (static登録)
    |       +-- NonRegisteringSparkConnectDriver.connect()
    |               +-- acceptsURL() [URL検証]
    |               +-- new SparkConnectConnection(url, info)
    |                       +-- SparkConnectClient.builder().build()
    |                       +-- SparkSession.builder().client().create()
    |
    +-- SparkConnectConnection
            +-- createStatement() -> SparkConnectStatement
            |       +-- execute(sql) -> spark.sql(sql)
            |       +-- executeQuery(sql) -> SparkConnectResultSet
            |
            +-- getMetaData() -> SparkConnectDatabaseMetaData
            +-- setCatalog() -> spark.catalog.setCurrentCatalog()
            +-- setSchema() -> spark.catalog.setCurrentDatabase()
            +-- close() -> spark.close()
```

### データフロー図

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

JDBC URL ──────────▶ DriverManager ──▶ SparkConnectDriver ──▶ Connection
SQL文字列 ──────────▶ Statement.execute() ──▶ SparkSession.sql() ──▶ DataFrame
                                                                        |
JDBC ResultSet ◀── SparkConnectResultSet ◀── DataFrame.collect() ◀──────+
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SparkConnectDriver.java | `sql/connect/client/jdbc/src/main/java/org/apache/spark/sql/connect/client/jdbc/SparkConnectDriver.java` | ソース | JDBCドライバー自動登録 |
| NonRegisteringSparkConnectDriver.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/NonRegisteringSparkConnectDriver.scala` | ソース | Driverインターフェース実装 |
| SparkConnectConnection.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectConnection.scala` | ソース | Connectionインターフェース実装 |
| SparkConnectStatement.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectStatement.scala` | ソース | Statementインターフェース実装 |
| SparkConnectResultSet.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectResultSet.scala` | ソース | ResultSetインターフェース実装 |
| SparkConnectResultSetMetaData.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectResultSetMetaData.scala` | ソース | ResultSetMetaData実装 |
| SparkConnectDatabaseMetaData.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectDatabaseMetaData.scala` | ソース | DatabaseMetaData実装 |
| JdbcTypeUtils.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/util/JdbcTypeUtils.scala` | ソース | Spark型とJDBC型の変換 |
| JdbcErrorUtils.scala | `sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/util/JdbcErrorUtils.scala` | ソース | JDBCエラーハンドリング |
