# 機能設計書 476-Copy-DbaAgentJobCategory

## 概要

本ドキュメントは、SQL Server Agentのジョブ、アラート、オペレーター用カスタムカテゴリをSQL Serverインスタンス間でコピーするPowerShellコマンド「Copy-DbaAgentJobCategory」の機能設計書である。

### 本機能の処理概要

Copy-DbaAgentJobCategoryは、SQL Server Agentのカスタムカテゴリ（ジョブカテゴリ、アラートカテゴリ、オペレーターカテゴリ）をソースインスタンスから1つ以上の宛先インスタンスにコピーする機能である。ユーザー定義カテゴリ（ID >= 100）のみを対象とし、システム組み込みカテゴリは保持される。

**業務上の目的・背景**：エンタープライズ環境では、ジョブを組織構造やアプリケーション別に分類するためにカスタムカテゴリが使用される。サーバー移行や環境構築時にこれらのカテゴリ構造を手動で再作成することは時間がかかる。本機能を使用することで、複数のSQL Serverインスタンス間で一貫したジョブ分類体系を維持でき、管理の効率化とミスの防止が可能になる。

**機能の利用シーン**：
- 新規サーバー構築時の標準カテゴリ構造の展開
- サーバー統合・移行プロジェクトでのカテゴリ移行
- 複数環境間でのカテゴリ標準化
- 災害復旧サーバーへのカテゴリ構成の複製

**主要な処理内容**：
1. ソースサーバーへの接続
2. 宛先サーバーへの接続
3. カテゴリタイプに基づく処理分岐（Job/Alert/Operator）
4. ユーザー定義カテゴリ（ID >= 100）のフィルタリング
5. 既存カテゴリとの重複チェック
6. SMOスクリプトによるカテゴリの作成
7. 処理結果の出力

**関連システム・外部連携**：SQL Server Agentサービス、msdbデータベース。

**権限による制御**：ソースおよび宛先の両方でsysadmin固定サーバーロールのメンバーシップが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | SQL Server Management Studio - SQL Server Agent - Jobs - Categories | 参照画面 | ジョブカテゴリの確認 |

## 機能種別

データ移行処理 / SMOスクリプティング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Source | DbaInstanceParameter | Yes | コピー元SQL Serverインスタンス | - |
| SourceSqlCredential | PSCredential | No | ソース接続用の資格情報 | - |
| Destination | DbaInstanceParameter[] | Yes | コピー先SQL Serverインスタンス（複数可） | - |
| DestinationSqlCredential | PSCredential | No | 宛先接続用の資格情報 | - |
| CategoryType | string[] | No | コピーするカテゴリタイプ | ValidateSet: Job, Alert, Operator |
| JobCategory | string[] | No | コピーするジョブカテゴリ名 | - |
| AgentCategory | string[] | No | コピーするアラートカテゴリ名 | 注: 現在未実装 |
| OperatorCategory | string[] | No | コピーするオペレーターカテゴリ名 | - |
| Force | switch | No | 既存カテゴリを削除して再作成 | - |
| WhatIf | switch | No | 実行内容のプレビュー | - |
| Confirm | switch | No | 実行前の確認プロンプト | - |
| EnableException | switch | No | 例外をスローするかどうか | - |

### 入力データソース

- ソースSQL ServerのJobServer.JobCategories
- ソースSQL ServerのJobServer.OperatorCategories
- ソースSQL ServerのJobServer.AlertCategories

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DateTime | DbaDateTime | 処理実行日時 |
| SourceServer | string | ソースSQL Serverインスタンス名 |
| DestinationServer | string | 宛先SQL Serverインスタンス名 |
| Name | string | カテゴリ名 |
| Type | string | オブジェクトタイプ（Agent Job Category, Agent Operator Category, Agent Alert Category） |
| Status | string | 処理結果（Successful, Failed, Skipped） |
| Notes | string | 追加情報（スキップ理由など） |

### 出力先

パイプライン出力（PSCustomObject - MigrationObject）

## 処理フロー

### 処理シーケンス

```
1. ソースサーバー接続（begin）
   └─ Connect-DbaInstanceでソースに接続
2. 宛先サーバー接続（process）
   └─ 各宛先インスタンスにConnect-DbaInstanceで接続
3. カテゴリタイプに基づく処理分岐
   ├─ CategoryType指定時: 指定されたタイプのみ処理
   └─ 個別カテゴリ指定時: 指定されたカテゴリのみ処理
4. 各カテゴリタイプの処理
   ├─ Copy-JobCategory（ジョブカテゴリ）
   ├─ Copy-OperatorCategory（オペレーターカテゴリ）
   └─ Copy-AlertCategory（アラートカテゴリ）
5. カテゴリごとの処理
   ├─ ユーザー定義カテゴリのフィルタリング（ID >= 100）
   ├─ 指定カテゴリによるフィルタリング
   ├─ 既存カテゴリの確認とForce処理
   └─ Script()でカテゴリ作成
6. 結果出力
   └─ 各操作ごとにMigrationObjectを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ソースサーバー接続]
    B --> C[foreach 宛先インスタンス]
    C --> D[宛先サーバー接続]
    D --> E{CategoryType指定?}
    E -->|Yes| F[指定タイプのみ処理]
    E -->|No| G{個別カテゴリ指定?}
    G -->|Yes| H[指定カテゴリのみ処理]
    G -->|No| I[全カテゴリタイプを処理]
    F --> J[switch CategoryType]
    J -->|Job| K[Copy-JobCategory]
    J -->|Alert| L[Copy-AlertCategory]
    J -->|Operator| M[Copy-OperatorCategory]
    H --> N[指定されたカテゴリ関数を呼び出し]
    I --> O[全カテゴリ関数を呼び出し]
    K --> P[ID >= 100のカテゴリをフィルタ]
    L --> P
    M --> P
    N --> P
    O --> P
    P --> Q{宛先に既存?}
    Q -->|Yes| R{Force指定?}
    R -->|No| S[Skipped: 既に存在]
    R -->|Yes| T[既存カテゴリを削除]
    Q -->|No| U[カテゴリ作成]
    T --> U
    U --> V{作成成功?}
    V -->|Yes| W[Successful]
    V -->|No| X[Failed]
    S --> Y[次のカテゴリへ]
    W --> Y
    X --> Y
    Y --> P
    P --> C
    C --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ユーザー定義カテゴリのみ | ID >= 100のカテゴリのみがコピー対象 | 常時 |
| BR-002 | システムカテゴリ保護 | システム組み込みカテゴリ（ID < 100）は対象外 | 常時 |
| BR-003 | Force動作 | Forceが指定された場合、既存カテゴリを削除して再作成 | 宛先に同名カテゴリが存在する場合 |
| BR-004 | AlertCategories要件 | アラートカテゴリはSQL Server 2005以降でのみサポート | AlertCategory処理時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| カテゴリ削除 | msdb.dbo.syscategories | DELETE | SMO Drop()により削除 |
| カテゴリ作成 | msdb.dbo.syscategories | INSERT | SMO Script()で生成したT-SQLを実行 |

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

#### msdb.dbo.syscategories

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | category_id, name, category_class | WHERE category_id >= 100 | ユーザー定義カテゴリ |
| INSERT | name, category_class, category_type | ソースカテゴリの設定値 | SMO Script()で生成 |
| DELETE | - | WHERE name = @categoryName | SMO Drop()で削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | ソースまたは宛先に接続できない | Stop-Functionで処理を中断 |
| VersionError | バージョンエラー | アラートカテゴリでSQL 2005未満 | throwで処理を中断 |
| DropError | 削除エラー | 既存カテゴリの削除に失敗 | Failedとして記録し次のカテゴリへ |
| CreateError | 作成エラー | カテゴリの作成に失敗 | Failedとして記録し次のカテゴリへ |

### リトライ仕様

リトライ処理は実装されていない。エラー発生時は次のカテゴリの処理に移行する。

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

個々のカテゴリ作成操作は独立したトランザクションとして実行される。一括トランザクションは使用されない。

## パフォーマンス要件

特になし。カテゴリ数に比例して処理時間が増加するが、通常は数秒程度。

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

- ソースおよび宛先の両方でsysadmin権限が必要
- SQL認証使用時は資格情報がSecureStringとして管理される
- WhatIfパラメータによる事前確認が可能

## 備考

- カテゴリはジョブ、アラート、オペレーターの組織化に使用される
- システム組み込みカテゴリ（Uncategorized等）は移行対象外
- カテゴリの移行はジョブ移行の前提作業として実行されることが多い

---

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

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

### 推奨読解順序

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

SMOのJobCategory、OperatorCategory、AlertCategoryオブジェクトの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Copy-DbaAgentJobCategory.ps1 | `public/Copy-DbaAgentJobCategory.ps1` | 126-203行目のCopy-JobCategory内部関数 |

**読解のコツ**: 各カテゴリタイプは$server.JobServer.XXXCategoriesコレクションに格納されており、IDプロパティでユーザー定義（>= 100）とシステム定義（< 100）を区別できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Copy-DbaAgentJobCategory.ps1 | `public/Copy-DbaAgentJobCategory.ps1` | 107-123行目のパラメータ定義、376-384行目のbeginブロック |

**主要処理フロー**:
1. **376-384行目**: beginブロックでソース接続
2. **385-431行目**: processブロックでカテゴリタイプに基づく処理分岐
3. **126-203行目**: Copy-JobCategory内部関数
4. **205-286行目**: Copy-OperatorCategory内部関数
5. **288-374行目**: Copy-AlertCategory内部関数

#### Step 3: カテゴリコピーロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Copy-DbaAgentJobCategory.ps1 | `public/Copy-DbaAgentJobCategory.ps1` | 142-143行目のID >= 100フィルタリング |

**主要処理フロー**:
- **142行目**: $sourceServer.JobServer.JobCategoriesでカテゴリ取得
- **142行目**: Where-Object ID -ge 100でユーザー定義のみフィルタ
- **162-183行目**: 既存確認とForce処理
- **186-199行目**: Script()でT-SQL生成し実行

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

```
Copy-DbaAgentJobCategory
    │
    ├─ Connect-DbaInstance（Source）
    │      └─ ソースサーバー接続
    │
    ├─ Connect-DbaInstance（Destination）
    │      └─ 宛先サーバー接続
    │
    ├─ Copy-JobCategory（内部関数）
    │      ├─ $sourceServer.JobServer.JobCategories
    │      ├─ Where-Object ID -ge 100
    │      ├─ $jobCategory.Drop()（Force時）
    │      └─ $jobCategory.Script() -> Query()
    │
    ├─ Copy-OperatorCategory（内部関数）
    │      ├─ $sourceServer.JobServer.OperatorCategories
    │      ├─ Where-Object ID -ge 100
    │      ├─ $operatorCategory.Drop()（Force時）
    │      └─ $operatorCategory.Script() -> Query()
    │
    └─ Copy-AlertCategory（内部関数）
           ├─ バージョンチェック（Major >= 9）
           ├─ $sourceServer.JobServer.AlertCategories
           ├─ Where-Object ID -ge 100
           ├─ $alertCategory.Drop()（Force時）
           └─ $alertCategory.Script() -> Query()
```

### データフロー図

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

Source           ───▶ Connect-DbaInstance ───▶ $sourceServer
                                │
                                ▼
Destination      ───▶ Connect-DbaInstance ───▶ $destServer
                                │
                                ▼
CategoryType     ───▶ 処理分岐 ───▶ Copy-XXXCategory
                        │
                        ▼
               ID >= 100 フィルタ
                        │
                        ▼
               既存確認 / Force処理
                        │
                        ▼
               Script() + Query()
                        │
                        ▼
                [MigrationObject出力]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Copy-DbaAgentJobCategory.ps1 | `public/Copy-DbaAgentJobCategory.ps1` | ソース | メイン処理ロジック |
| Copy-DbaAgentJob.ps1 | `public/Copy-DbaAgentJob.ps1` | ソース | ジョブコピー（カテゴリが前提） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続用コマンド |
