# 機能設計書 11-データクエリノード

## 概要

本ドキュメントは、Giselleワークフローエンジンにおけるデータクエリノード（DataQueryNode）の機能設計を記述する。データクエリノードは、外部データストア（PostgreSQL等）に対してSQLクエリを実行し、結果をワークフロー内で利用可能にするための操作ノードである。

### 本機能の処理概要

データクエリノードは、ワークフロー内でデータベースに対する動的なクエリ実行を可能にする機能である。ユーザーが定義したSQLクエリを、接続されたデータストアに対して実行し、その結果を後続のノードで利用できる形式で出力する。

**業務上の目的・背景**：AIワークフローにおいて、外部データベースからリアルタイムにデータを取得し、そのデータを基にAI処理を行うユースケースが増加している。例えば、顧客データベースから特定の条件に合致するレコードを取得し、それを基にAIが分析やレポート生成を行うケースがある。本機能は、そのようなデータ駆動型のAIワークフローを実現するための基盤となる。

**機能の利用シーン**：
- データベースから顧客情報を取得してAIによる分析を行う場合
- 在庫データを取得して自動発注判断を行う場合
- ログデータを取得してAIによる異常検知を行う場合
- LLMが生成したSQLクエリを実行してデータを取得する場合

**主要な処理内容**：
1. ユーザー定義のSQLクエリを解析し、パラメータプレースホルダーを特定
2. 接続されたデータストアノードから接続情報を取得
3. シークレット管理機能から暗号化された接続文字列を復号
4. PostgreSQL接続プールを作成し、クエリを実行
5. キャンセル要求のポーリングによる中断対応
6. 結果を構造化して後続ノードへ出力

**関連システム・外部連携**：
- PostgreSQLデータベース（外部データストア）
- シークレット管理機能（接続文字列の暗号化・復号）
- データストアレジストリ（接続設定の解析）

**権限による制御**：データストアへの接続はワークスペース単位で管理され、シークレットとして保存された接続情報を使用する。直接的な権限チェックはワークスペースアクセス権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主画面 | データクエリノードの追加・編集、クエリの入力と実行結果の確認 |

## 機能種別

データ連携 / CRUD操作（SELECT）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| query | string | Yes | 実行するSQLクエリ文字列 | 空文字列でないこと |
| dataStoreId | DataStoreId | Yes | 接続先データストアのID | 有効なDataStoreId形式（ds-で始まる） |

### 入力データソース

- **クエリ文字列**: ノードプロパティパネルからのユーザー入力、またはテキストエディタでのJSON形式入力
- **データストア接続**: 接続されたDataStoreNodeから取得
- **動的パラメータ**: 接続された他ノード（テキストノード、テキスト生成ノード等）からの出力値

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| type | "data-query-result" | 出力タイプの識別子 |
| outputId | OutputId | 出力ポートのID |
| content.type | "data-query" | コンテンツタイプ |
| content.dataStoreId | DataStoreId | クエリ実行対象のデータストアID |
| content.rows | any[] | クエリ結果の行データ配列 |
| content.rowCount | number | 結果の行数 |
| content.query | string | 実際に実行されたクエリ（表示用） |

### 出力先

- ワークフロー内の後続ノード（テキスト生成ノード等）への接続を通じたデータ提供
- タスク実行結果としてのストレージ保存

## 処理フロー

### 処理シーケンス

```
1. クエリ解析とパラメータ化
   └─ SQLクエリ内の{{nodeId:outputId}}形式のプレースホルダーを検出
   └─ ユーザー入力はパラメータ化（$1, $2等）、LLM生成SQLは直接置換

2. データストア接続情報の取得
   └─ 接続されたDataStoreNodeからdataStoreIdを取得
   └─ データストア設定を取得し、接続文字列のシークレットIDを特定

3. シークレット復号
   └─ Vault機能を使用して暗号化された接続文字列を復号

4. キャンセル確認（実行前）
   └─ ユーザーによるキャンセル要求がないか確認

5. 接続プール作成とクエリ実行
   └─ PostgreSQL接続プールを作成（タイムアウト設定付き）
   └─ ポーリングによるキャンセル監視を開始
   └─ パラメータ化されたクエリを実行

6. 結果処理と出力
   └─ クエリ結果をGenerationOutput形式に変換
   └─ 生成完了としてマーク
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[クエリ解析・パラメータ化]
    B --> C[DataStoreNode接続確認]
    C --> D{DataStore設定済み?}
    D -->|No| E[エラー: 未設定]
    D -->|Yes| F[データストア設定取得]
    F --> G[シークレット復号]
    G --> H{キャンセル確認}
    H -->|キャンセル| I[処理中断]
    H -->|継続| J[接続プール作成]
    J --> K[クエリ実行開始]
    K --> L{ポーリング監視}
    L -->|キャンセル| M[pg_cancel_backend]
    L -->|完了| N[結果取得]
    M --> I
    N --> O{キャンセル確認}
    O -->|キャンセル| I
    O -->|継続| P[結果を出力形式に変換]
    P --> Q[Generation完了]
    Q --> R[終了]
    E --> R
    I --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | パラメータ化ルール | ユーザー入力（テキストノード等）はSQLインジェクション防止のためパラメータ化される | テキストノード、トリガーノード、アクションノードからの入力時 |
| BR-002 | LLM生成SQL直接実行 | テキスト生成ノードからの出力は完全なSQLとして直接実行される | textGeneration、contentGenerationノードからの入力時 |
| BR-003 | コードブロック除去 | LLM出力に含まれるMarkdownコードブロック（```sql...```）は自動的に除去される | LLM生成SQLの処理時 |
| BR-004 | タイムアウト制御 | クエリ実行は60秒でタイムアウトする | 全てのクエリ実行時 |

### 計算ロジック

クエリパラメータ化処理:
- 同一プレースホルダーキーは同一パラメータインデックスを再利用
- パラメータは$1, $2, ...の形式でPostgreSQLプレースホルダーに変換
- クォートされたプレースホルダー（'{{...}}'）はクォートを除去してパラメータ化

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| クエリ実行 | ユーザー指定テーブル | SELECT | ユーザーが定義したSQLクエリの実行 |

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

#### 外部データストア（PostgreSQL）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | ユーザー指定 | ユーザー定義のWHERE条件 | パラメータ化されたクエリとして実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | DataQueryError | 接続失敗、クエリ構文エラー、タイムアウト等 | エラーメッセージを含むFailedGenerationとして記録 |
| - | Error | DataStoreNodeが未接続 | "No Data Store node connected to Data Query node" |
| - | Error | DataStoreが未設定 | "Data Store node is not configured" |
| - | Error | DataStoreが見つからない | "DataStore not found: {dataStoreId}" |
| 57014 | PostgreSQLエラー | クエリキャンセルまたはタイムアウト | キャンセル要求の場合は正常終了、それ以外はDataQueryError |

### リトライ仕様

本機能はリトライ機構を持たない。エラー発生時は即座に失敗として処理される。

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

- 各クエリは独立したトランザクションとして実行される
- 明示的なトランザクション制御はユーザーのSQLに委ねられる
- クエリ完了後、接続プールは適切にクリーンアップされる

## パフォーマンス要件

| 項目 | 要件値 |
|-----|-------|
| 接続タイムアウト | 10,000ms |
| クエリタイムアウト | 65,000ms |
| ステートメントタイムアウト | 60,000ms |
| キャンセルポーリング間隔 | 2,500ms |

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

- **SQLインジェクション対策**: ユーザー入力値はパラメータ化によりSQLインジェクションを防止
- **接続文字列の保護**: 接続文字列はVault機能により暗号化保存、使用時のみ復号
- **LLM生成SQL**: LLMからの出力は直接実行されるため、プロンプトインジェクションのリスクあり（設計上の許容事項）

## 備考

- 複数ステートメントを含むクエリ（"SELECT 1; SELECT 2"等）の場合、最後の結果のみが返却される
- クエリ結果はJSON形式でシリアライズ可能な形式で出力される

---

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

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

### 推奨読解順序

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

まず、データクエリノードのスキーマ定義とノード構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | data-query.ts | `packages/protocol/src/node/operations/data-query.ts` | DataQueryContentのスキーマ定義、queryプロパティの構造 |
| 1-2 | operation-node.ts | `packages/protocol/src/node/operations/operation-node.ts` | DataQueryNodeの型定義、isDataQueryNode判定関数 |
| 1-3 | data-store.ts | `packages/protocol/src/node/variables/data-store.ts` | DataStoreContentのスキーマ、configured/unconfigured状態 |

**読解のコツ**: Zodスキーマを使用した型定義パターンに注目。z.object、z.discriminatedUnion等の使用法を理解すると全体像が掴みやすい。

#### Step 2: ノード生成ファクトリを理解する

ノードがどのように生成されるかを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | node-factories.ts | `packages/node-registry/src/node-factories.ts` | dataQueryFactoryImplの実装、createDataQueryNode関数 |

**主要処理フロー**:
- **676-711行目**: dataQueryFactoryImplのcreate/clone実装
- **1031-1033行目**: createDataQueryNode関数のエクスポート

#### Step 3: クエリ実行ロジックを理解する

本機能の中核であるクエリ実行処理を詳細に把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | execute-data-query.ts | `packages/giselle/src/operations/execute-data-query.ts` | executeDataQuery関数の全体フロー |

**主要処理フロー**:
- **51-63行目**: createPollingQueryExecutorによるキャンセル監視付きクエリ実行器の作成
- **126-292行目**: executeDataQuery関数の本体、useGenerationExecutorによる実行フロー
- **345-379行目**: parameterizeQuery関数によるSQLパラメータ化処理
- **381-589行目**: resolveQuery関数による動的パラメータ解決

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

```
executeDataQuery (execute-data-query.ts)
    │
    ├─ useGenerationExecutor
    │      └─ execute callback
    │             │
    │             ├─ resolveQuery
    │             │      ├─ generationContentResolver
    │             │      └─ parameterizeQuery
    │             │
    │             ├─ getDataStore
    │             │
    │             ├─ parseConfiguration (data-store-registry)
    │             │
    │             ├─ vault.decrypt
    │             │
    │             └─ createPollingQueryExecutor
    │                    ├─ execute (Pool.query)
    │                    └─ cleanup (Pool.end)
    │
    └─ finishGeneration / setGeneration
```

### データフロー図

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

SQLクエリ文字列 ───▶ resolveQuery ───▶ パラメータ化クエリ
                          │
DataStoreNode ─────▶ getDataStore ───▶ 接続設定
                          │
シークレット ──────▶ vault.decrypt ───▶ 接続文字列
                          │
                   createPollingQueryExecutor
                          │
                   PostgreSQL Pool
                          │
                   Pool.query ─────────────────────▶ QueryResult
                          │
                   finishGeneration ────────────────▶ GenerationOutput
                                                        ├─ rows[]
                                                        ├─ rowCount
                                                        └─ query
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| data-query.ts | `packages/protocol/src/node/operations/data-query.ts` | ソース | DataQueryContentスキーマ定義 |
| operation-node.ts | `packages/protocol/src/node/operations/operation-node.ts` | ソース | DataQueryNode型定義、isDataQueryNode判定 |
| data-store.ts | `packages/protocol/src/node/variables/data-store.ts` | ソース | DataStoreContentスキーマ定義 |
| execute-data-query.ts | `packages/giselle/src/operations/execute-data-query.ts` | ソース | クエリ実行ロジック本体 |
| node-factories.ts | `packages/node-registry/src/node-factories.ts` | ソース | ノード生成ファクトリ |
| get-data-store.ts | `packages/giselle/src/data-stores/get-data-store.ts` | ソース | データストア情報取得 |
| data-query-properties-panel | `internal-packages/workflow-designer-ui/src/editor/properties-panel/data-query-properties-panel/` | ソース | UIプロパティパネル |
