# 機能設計書 450-Invoke-DbaXEReplay

## 概要

本ドキュメントは、拡張イベントファイルにキャプチャされたSQLクエリをターゲットSQL Serverインスタンスに対してリプレイするdbatools PowerShellコマンドレット `Invoke-DbaXEReplay` の機能設計を記述する。

### 本機能の処理概要

Invoke-DbaXEReplayは、拡張イベント（Extended Events）でキャプチャされたSQLワークロードを1つ以上のターゲットSQL Serverインスタンスに対してリプレイし、パフォーマンステストや負荷シミュレーションを行うコマンドレットである。

**業務上の目的・背景**：本番環境で実行されたSQLワークロードをテスト環境で再現することは、パフォーマンステスト、キャパシティプランニング、クエリ動作のトラブルシューティングに不可欠である。この機能により、データベース管理者は拡張イベントでキャプチャされた実際のワークロードを安全にテスト環境でリプレイし、変更の影響を検証できる。

**機能の利用シーン**：
- パフォーマンス変更（インデックス追加、統計更新など）の検証時に本番ワークロードを再現する場面
- テスト環境でのキャパシティプランニング
- クエリ動作のデバッグと分析
- 複数サーバーに対する同一ワークロードの比較テスト

**主要な処理内容**：
1. sqlcmdコマンドの存在を確認
2. 一時SQLファイルを作成
3. Read-DbaXEFileからパイプラインで受け取ったイベントをフィルタリング
4. sql_batch_completedまたはrcp_completedイベントのSQLステートメントを抽出
5. ALTER EVENT SESSION以外のステートメントを一時ファイルに書き込み（GOバッチセパレータ付き）
6. 各ターゲットインスタンスに対してsqlcmdでスクリプトを実行
7. 結果を出力し、一時ファイルを削除

**関連システム・外部連携**：
- Read-DbaXEFileまたはRead-DbaXESessionからのパイプライン入力に依存
- sqlcmdコマンドラインツールを使用してSQLを実行
- 拡張イベント（.xel）ファイルからイベントデータを取得

**権限による制御**：
- ターゲットSQL Serverインスタンスへのクエリ実行権限が必要
- sqlcmdへのシステムアクセスが必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIコマンド | 主画面 | PowerShellコマンドラインから直接実行 |

## 機能種別

データ処理 / クエリ実行 / テスト支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstance[] | Yes | SQLを実行するターゲットSQL Serverインスタンス | 有効なSQL Serverインスタンス名 |
| SqlCredential | PSCredential | No | 代替認証情報 | Get-Credentialで取得した有効な認証情報 |
| Database | string[] | No | 初期データベースコンテキスト | 有効なデータベース名 |
| Event | string[] | No | リプレイ対象のイベントタイプ（デフォルト: sql_batch_completed, rcp_completed） | 有効なイベント名 |
| InputObject | object | Yes | Read-DbaXEFileまたはRead-DbaXESessionからの拡張イベントオブジェクト | パイプライン入力必須 |
| Raw | switch | No | sqlcmd出力をクリーンアップせずにそのまま表示 | - |
| EnableException | switch | No | 例外処理を有効化 | - |

### 入力データソース

パイプライン入力（Read-DbaXEFile、Read-DbaXESessionからの拡張イベントオブジェクト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (結果) | System.String | sqlcmd実行からの出力結果 |

### 出力先

PowerShellコンソール（System.String）

## 処理フロー

### 処理シーケンス

```
1. beginブロック
   └─ sqlcmdの存在確認
   └─ 一時SQLファイルの作成（dbatools-replay-{timestamp}.sql）
2. processブロック
   └─ Test-FunctionInterruptで中断チェック
   └─ イベント名がEventパラメータに含まれるか確認
   └─ statementまたはbatch_textからSQLを抽出
   └─ ALTER EVENT SESSION以外のステートメントをファイルに追記
   └─ GOバッチセパレータを追加
3. endブロック
   └─ Test-FunctionInterruptで中断チェック
   └─ 各SqlInstanceに対してループ
       └─ Connect-DbaInstanceで接続確認
       └─ Raw指定時: sqlcmdを直接実行
       └─ 通常時: sqlcmd出力をキャプチャしてクリーンアップ
   └─ 一時ファイルを削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{sqlcmd存在?}
    B -->|No| C[Stop-Function]
    B -->|Yes| D[一時ファイル作成]
    D --> E[processブロック]
    E --> F{Event一致?}
    F -->|No| G[スキップ]
    F -->|Yes| H{statement存在?}
    H -->|Yes| I{ALTER EVENT SESSION?}
    H -->|No| J[batch_text取得]
    J --> I
    I -->|Yes| G
    I -->|No| K[ファイルに追記]
    K --> L[GO追加]
    L --> M{次のイベント?}
    G --> M
    M -->|Yes| E
    M -->|No| N[endブロック]
    N --> O[SqlInstanceループ]
    O --> P[Connect-DbaInstance]
    P --> Q{Raw?}
    Q -->|Yes| R[sqlcmd直接実行]
    Q -->|No| S[sqlcmd出力キャプチャ]
    S --> T[出力クリーンアップ]
    R --> U{次のInstance?}
    T --> U
    U -->|Yes| O
    U -->|No| V[一時ファイル削除]
    V --> W[終了]
    C --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | sqlcmd必須 | sqlcmdがインストールされていない場合は処理停止 | 常時 |
| BR-002 | デフォルトイベント | Eventパラメータ未指定時はsql_batch_completedとrcp_completedを処理 | Event未指定時 |
| BR-003 | ALTER EVENT SESSION除外 | ALTER EVENT SESSIONステートメントはリプレイ対象外 | 常時 |
| BR-004 | GOセパレータ追加 | 各ステートメントの後にGOバッチセパレータを追加 | 常時 |

### 計算ロジック

一時ファイル名の生成:
```powershell
$timestamp = (Get-Date -Format yyyyMMddHHmm)
$temp = ([System.IO.Path]::GetTempPath()).TrimEnd("\")
$filename = "$temp\dbatools-replay-$timestamp.sql"
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リプレイクエリ実行 | （入力イベントに依存） | SELECT/INSERT/UPDATE/DELETE/その他 | キャプチャされたSQLを再実行 |

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

リプレイされるSQLの内容に依存するため、事前に内容を確認することを推奨。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ToolError | sqlcmdがインストールされていない | SQL Server Command Line Utilitiesをインストール |
| - | ConnectionError | SQL Serverインスタンスへの接続失敗 | 接続情報を確認し再試行 |
| - | ExecutionError | SQLクエリ実行失敗 | エラーメッセージを確認 |

### リトライ仕様

自動リトライは行わない。エラーはそのまま出力される。

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

リプレイされるSQLの内容に依存する。各バッチは独立して実行される。

## パフォーマンス要件

リプレイされるSQLの数と複雑さに依存する。大量のクエリをリプレイする場合は長時間かかる可能性がある。

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

- SQL認証を使用する場合、認証情報はsqlcmdコマンドラインに渡される
- リプレイされるSQLは本番環境からキャプチャされたものである可能性があり、データ変更を含む場合がある
- テスト環境でのみ使用することを推奨

## 備考

- Raw指定時はsqlcmd出力がそのまま表示される（ヘッダー、フォーマット行を含む）
- 通常時は出力からダッシュ行（---...）がフィルタリングされる
- 一時ファイルは処理終了時に自動削除される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Read-DbaXEFile | - | 拡張イベントファイルからのイベントオブジェクト構造 |

**読解のコツ**: InputObjectのstatementまたはbatch_textプロパティにSQLが格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaXEReplay.ps1 | `public/Invoke-DbaXEReplay.ps1` | メインのコマンドレット実装 |

**主要処理フロー**:
1. **97-108行目**: beginブロックでsqlcmd確認と一時ファイル作成
2. **110-114行目**: イベントフィルタリング
3. **116-126行目**: ステートメント抽出とファイル追記
4. **130-135行目**: Connect-DbaInstanceで接続
5. **138-146行目**: Raw時のsqlcmd実行
6. **149-161行目**: 通常時のsqlcmd実行と出力クリーンアップ
7. **163行目**: 一時ファイル削除

#### Step 3: 依存関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Read-DbaXEFile | - | 拡張イベントファイルの読み込み |
| 3-2 | Connect-DbaInstance | - | SQL Server接続 |

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

```
Invoke-DbaXEReplay
    │
    ├─ Get-Command sqlcmd (begin)
    │
    ├─ Set-Content / Add-Content (process)
    │
    ├─ Connect-DbaInstance (end)
    │
    └─ sqlcmd (end)
           └─ 一時SQLファイルを実行
```

### データフロー図

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

Read-DbaXEFile ───────────────▶ イベントフィルタリング
       │                              │
       │                       ステートメント抽出
       │                              │
       │                       ALTER EVENT SESSION除外
       │                              │
       │                       一時ファイル作成
       │                              │
       └──────────────────────▶ GOセパレータ追加 ────────────────────▶ .sqlファイル
                                      │
SqlInstance ──────────────────▶ Connect-DbaInstance
                                      │
SqlCredential ────────────────▶ sqlcmd実行
                                      │
Raw ──────────────────────────▶ 出力処理（クリーンアップ/そのまま）
                                      │
                                      ▼
                               sqlcmd出力（System.String）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaXEReplay.ps1 | `public/Invoke-DbaXEReplay.ps1` | ソース | メインコマンドレット実装 |
| Invoke-DbaXEReplay.Tests.ps1 | `tests/Invoke-DbaXEReplay.Tests.ps1` | テスト | ユニットテスト |
