# 画面設計書 144-Painlessスクリプト実行

## 概要

本ドキュメントは、OpenSearchのPainlessスクリプト実行API（GET/POST /_scripts/painless/_execute）の画面設計書である。任意のPainlessスクリプトを実行し結果を返すREST APIエンドポイントの仕様を定義する。

### 本画面の処理概要

本APIは、Painlessスクリプトをテスト目的で即座に実行し、その結果を確認するためのAPIである。インデックスに影響を与えることなく、スクリプトの動作を検証できる。

**業務上の目的・背景**：Painlessスクリプトは検索スコアリング、ドキュメント更新、インジェスト処理等で利用されるが、本番環境に適用する前にスクリプトの動作を検証する手段が必要である。本APIにより、スクリプトのデバッグやテストを安全に実行できる。特にフィルタスクリプトやスコアスクリプトの動作確認において重要な役割を果たす。

**画面へのアクセス方法**：REST APIクライアント（curl、Kibana Dev Tools等）から `GET/POST /_scripts/painless/_execute` エンドポイントにリクエストを送信する。スクリプト内容はリクエストボディで指定する。

**主要な操作・処理内容**：
1. クライアントがスクリプト定義をリクエストボディに含めてリクエストを送信する
2. PainlessExecuteActionがスクリプトを解析する
3. 指定されたコンテキスト（painless_test、filter、score等）に応じてスクリプトを実行する
4. コンテキストに応じて一時的なLuceneインデックスが作成される場合がある
5. スクリプトの実行結果がJSON形式で返却される

**画面遷移**：「スクリプトコンテキスト一覧」（No.142）で利用可能なコンテキストを確認した後、本APIでスクリプトをテスト実行する。検証が完了したスクリプトは「スクリプト作成・更新」（No.140）で永続化される。

**権限による表示制御**：スクリプトの実行権限が必要である。インデックスを指定する場合、そのインデックスへの読み取り権限も必要となる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | Painlessスクリプト | 主機能 | 任意のPainlessスクリプトを実行し結果を返す処理 |

## 画面種別

実行操作（API）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET | `/_scripts/painless/_execute` | Painlessスクリプトを実行する |
| POST | `/_scripts/painless/_execute` | Painlessスクリプトを実行する |

## 入出力項目

### クエリパラメータ

パラメータなし。

### リクエストボディ

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| script | object | Yes | 実行するスクリプト定義 |
| script.source | string | Yes | スクリプトのソースコード |
| script.lang | string | No | スクリプト言語（デフォルト: painless） |
| script.params | object | No | スクリプトに渡すパラメータ |
| context | string | No | スクリプト実行コンテキスト（painless_test、filter、score等） |
| context_setup | object | No | コンテキスト設定 |
| context_setup.index | string | No | 使用するインデックス名 |
| context_setup.document | object | No | テスト用ドキュメント |
| context_setup.query | object | No | テスト用クエリ（scoreコンテキスト時） |

## 表示項目

### レスポンスフィールド

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | varies | スクリプトの実行結果（コンテキストにより型が異なる） |

## イベント仕様

### 1-Painlessスクリプト実行リクエスト

1. クライアントがスクリプト定義をリクエストボディに含めてリクエストを送信する
2. PainlessExecuteAction内のRestHandlerがリクエストを受け付ける
3. リクエストボディからScript、context、context_setupが解析される
4. コンテキストに応じた実行環境が構築される:
   - **painless_test**: デフォルトコンテキスト。単純なスクリプト実行
   - **filter**: FilterScriptとして実行。一時Luceneインデックスを使用
   - **score**: ScoreScriptとして実行。一時Luceneインデックスとクエリを使用
5. スクリプトがコンパイルされ、実行結果が返却される

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| スクリプト実行 | - | なし | 永続的なデータ変更なし。一時的なインメモリLuceneインデックスのみ使用 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|----------|
| - | 成功 | `{"result": <実行結果>}` | スクリプト実行が正常に完了した場合 |
| - | エラー | `script_exception` | スクリプトのコンパイルエラーまたは実行時エラー |
| - | エラー | `illegal_argument_exception` | 不正なコンテキスト指定や不正なパラメータ |

## 例外処理

| 例外 | 状況 | HTTPステータス |
|------|------|---------------|
| ScriptException | スクリプトのコンパイルエラーまたは実行時エラー | 400 |
| IllegalArgumentException | 不正なコンテキストや不正なパラメータ | 400 |
| ResourceNotFoundException | 指定されたインデックスが存在しない | 404 |

## 備考

- API安定性: experimental（実験的）
- lang-painlessモジュールとして実装されており、Painless言語プラグインが有効である必要がある
- scoreコンテキストではLuceneのIndexWriter/IndexReaderを一時的に作成してスクリプトを実行する
- filterコンテキストではFilterScriptファクトリを使用してスクリプトを実行する
- SingleShardRequestベースの実装であり、インデックス指定時はそのシャードで実行される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | scripts_painless_execute.json | `rest-api-spec/src/main/resources/rest-api-spec/api/scripts_painless_execute.json` | REST API仕様定義。GET/POSTの両メソッドをサポートし、ボディが必要であることを確認 |
| 1-2 | PainlessExecuteAction.java | `modules/lang-painless/src/main/java/org/opensearch/painless/action/PainlessExecuteAction.java` | メインの実装ファイル。Request/Response内部クラス、コンテキスト定義を確認する |

**読解のコツ**: PainlessExecuteActionは単一ファイルにAction、Request、Response、RestHandler、TransportActionがすべて定義されている大きなクラスである。内部クラスの構造を先に把握することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PainlessExecuteAction.java（RestHandler内部クラス） | `modules/lang-painless/src/main/java/org/opensearch/painless/action/PainlessExecuteAction.java` | RestHandlerクラスのprepareRequestメソッドでリクエスト解析とアクション実行を確認する |

**主要処理フロー**:
1. RestHandler.prepareRequestでリクエストボディを解析
2. PainlessExecuteAction.Request.parseでScript、context、context_setupを構築
3. TransportAction.shardOperationで実際のスクリプト実行

#### Step 3: スクリプト実行層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PainlessExecuteAction.java（TransportAction内部クラス） | `modules/lang-painless/src/main/java/org/opensearch/painless/action/PainlessExecuteAction.java` | shardOperationメソッドでコンテキスト別の実行ロジックを確認する |

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

```
PainlessExecuteAction.RestHandler.prepareRequest()
    |
    +-- PainlessExecuteAction.Request.parse()（リクエスト解析）
    |
    +-- client.execute(PainlessExecuteAction.INSTANCE, request)
            |
            +-- PainlessExecuteAction.TransportAction.shardOperation()
                    |
                    +-- ScriptService.compile()（スクリプトコンパイル）
                    |
                    +-- コンテキスト別実行:
                    |   +-- painless_test: PainlessTestScript実行
                    |   +-- filter: FilterScript実行（一時Luceneインデックス使用）
                    |   +-- score: ScoreScript実行（一時Luceneインデックス+クエリ使用）
                    |
                    +-- PainlessExecuteAction.Response（結果返却）
```

### データフロー図

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

POST /_scripts/painless/_execute --> RestHandler                --> Request解析
  {script, context,                  (ボディ解析)
   context_setup}
                                          |
                                          v
                                     TransportAction.shardOperation()
                                     (コンテキスト別実行)
                                          |
                                          v
                                     ScriptService.compile()
                                     (Painlessスクリプトコンパイル)
                                          |
                                          v
                                     スクリプト実行 ----------> {"result": <結果>}
                                     (一時Luceneインデックス使用)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| scripts_painless_execute.json | `rest-api-spec/src/main/resources/rest-api-spec/api/scripts_painless_execute.json` | API仕様 | REST API仕様定義 |
| PainlessExecuteAction.java | `modules/lang-painless/src/main/java/org/opensearch/painless/action/PainlessExecuteAction.java` | ソース | メイン実装（Action/Request/Response/RestHandler/TransportAction） |
| ScriptService.java | `server/src/main/java/org/opensearch/script/ScriptService.java` | ソース | スクリプトコンパイル・実行サービス |
| FilterScript.java | `server/src/main/java/org/opensearch/script/FilterScript.java` | ソース | フィルタスクリプトコンテキスト |
| ScoreScript.java | `server/src/main/java/org/opensearch/script/ScoreScript.java` | ソース | スコアスクリプトコンテキスト |
