# 機能設計書 465-Move-DbaRegServerGroup

## 概要

本ドキュメントは、SQL Server Central Management Server (CMS)内で登録済みサーバーグループを別の親グループに移動するMove-DbaRegServerGroup機能の設計を記述する。

### 本機能の処理概要

Move-DbaRegServerGroupは、Central Management Server階層内で登録済みサーバーグループを新しい場所に移動する機能である。SQL Server Management Studioを使用せずに、CMSのグループ構造を再編成できる。

**業務上の目的・背景**：Central Management Serverは、複数のSQL Serverインスタンスを組織的に管理するための重要な機能である。環境の成長や組織変更に伴い、CMSのグループ構造を再編成する必要が生じることがある。この機能を使用することで、DBAはSSMSのGUIを使わずに、スクリプトベースでグループの移動を自動化でき、大規模な環境管理の効率化に貢献する。

**機能の利用シーン**：
- CMSグループ構造の再編成時
- 環境変更に伴うサーバーグループの再配置
- 自動化スクリプトでのCMS管理
- 開発環境から本番環境へのCMS構成の移行準備

**主要な処理内容**：
1. 移動対象のサーバーグループを特定（SqlInstanceとGroupまたはInputObject）
2. 移動先グループの存在を確認
3. SMOのScriptMove()メソッドを使用してグループを移動
4. 移動後のグループオブジェクトを返却

**関連システム・外部連携**：Get-DbaRegServerGroupからパイプライン入力を受け取ることができる。SMOのRegisteredServers名前空間を使用する。

**権限による制御**：CMSへの書き込み権限が必要。通常はsysadminロールまたはCMS管理権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 146 | 登録済みサーバーグループ | 補助機能 | 登録済みサーバーグループの移動 |

## 機能種別

UPDATE / 構成変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | CMSが存在するSQL Serverインスタンス | - |
| SqlCredential | PSCredential | No | 代替認証情報 | - |
| Group | String[] | No | 移動するサーバーグループのパス | SqlInstance指定時は必須 |
| NewGroup | String | Yes | 移動先グループのパス。'Default'でルートレベルに移動 | - |
| InputObject | Microsoft.SqlServer.Management.RegisteredServers.ServerGroup[] | No | 移動するServerGroupオブジェクト | ValueFromPipeline |
| EnableException | switch | No | 例外を直接スローするかどうか | - |

### 入力データソース

- パラメータ入力（SqlInstance、Group、NewGroup）
- パイプライン入力（ServerGroupオブジェクト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | String | CMSホストのコンピュータ名 |
| InstanceName | String | CMSのSQL Serverインスタンス名 |
| SqlInstance | String | 完全なSQL Serverインスタンス名 |
| Name | String | 移動されたサーバーグループの名前 |
| DisplayName | String | UI表示用の名前 |
| Description | String | グループの説明 |
| ServerGroups | ServerGroupCollection | ネストされた子サーバーグループ |
| RegisteredServers | RegisteredServerCollection | グループに属する登録済みサーバー |

### 出力先

- PowerShellパイプライン（標準出力）
- Microsoft.SqlServer.Management.RegisteredServers.ServerGroup オブジェクト

## 処理フロー

### 処理シーケンス

```
1. begin ブロック: パラメータ検証
   └─ SqlInstance指定時はGroupも必須であることを確認
2. SqlInstanceが指定されている場合、Get-DbaRegServerGroupを呼び出し
   └─ ServerGroupオブジェクトをInputObjectに追加
3. 各ServerGroupオブジェクトに対して繰り返し処理
4. Get-RegServerParentで親サーバーを取得
5. 移動先グループの取得
   ├─ NewGroup == 'Default': ルートグループ（Id=1）を取得
   └─ その他: 指定されたグループパスを取得
6. 移動先グループが存在しない場合はエラー
7. ShouldProcessで確認後、ScriptMove()でSQL生成・実行
8. 移動後のグループを取得して出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance指定?}
    B -->|Yes| C{Group指定?}
    C -->|No| D[Stop-Function: Group必須]
    C -->|Yes| E[Get-DbaRegServerGroup呼び出し]
    B -->|No| F[InputObject使用]
    E --> F
    F --> G[ServerGroupループ開始]
    G --> H[Get-RegServerParentで親取得]
    H --> I{NewGroup == Default?}
    I -->|Yes| J[Id=1のルートグループ取得]
    I -->|No| K[NewGroupパスでグループ取得]
    J --> L{グループ存在?}
    K --> L
    L -->|No| M[Stop-Function: グループ未発見]
    L -->|Yes| N{ShouldProcess確認}
    M --> G
    N -->|Yes| O[ScriptMove実行]
    N -->|No| G
    O --> P[移動後グループを取得・出力]
    P --> Q[接続を切断]
    Q --> G
    G --> R[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | Group必須条件 | SqlInstance指定時はGroupパラメータも必須 | SqlInstance使用時 |
| BR-002 | Defaultグループ | NewGroup='Default'でルートレベルに移動 | ルート移動時 |
| BR-003 | 移動先存在確認 | 移動先グループが存在しない場合はエラー | 常に適用 |
| BR-004 | パイプラインサポート | Get-DbaRegServerGroupからの出力をパイプラインで受け取り可能 | パイプライン使用時 |
| BR-005 | ShouldProcess対応 | -WhatIfと-Confirmをサポート | 常に適用 |

### 計算ロジック

該当なし（構成変更機能のため）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ移動 | msdb.dbo.sysmanagement_shared_server_groups | UPDATE | サーバーグループの親グループIDを更新 |

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

SMOのScriptMove()メソッドが内部的にT-SQLを生成・実行する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | パラメータエラー | SqlInstance指定時にGroupが未指定 | Groupパラメータを指定 |
| - | グループ未発見 | 移動先グループが存在しない | 移動先グループを事前に作成 |
| - | 移動失敗 | ScriptMove実行時のエラー | エラーメッセージを確認 |
| - | 親取得失敗 | Get-RegServerParentがnullを返す | CMSの接続状態を確認 |

### リトライ仕様

リトライ処理は実装されていない。

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

SMOのScriptMove()による単一操作。明示的なトランザクション管理は実装されていない。

## パフォーマンス要件

- メタデータ操作のため、軽量な処理
- 通常1秒未満で完了

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

- CMSへの書き込み権限が必要
- sysadminロールまたはCMS管理権限が推奨
- ShouldProcessによる確認機能を提供

## 備考

- Azure Data Studioの登録済みサーバーグループは操作不可
- 移動操作後は接続が自動的に切断される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Move-DbaRegServerGroup.ps1 | `public/Move-DbaRegServerGroup.ps1` | .OUTPUTSセクション（53-68行目）で出力オブジェクトの構造を確認 |

**読解のコツ**: 出力はMicrosoft.SqlServer.Management.RegisteredServers.ServerGroupクラス。Select-DefaultViewでカスタム表示プロパティが設定される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Move-DbaRegServerGroup.ps1 | `public/Move-DbaRegServerGroup.ps1` | beginブロック（92-96行目）でパラメータ検証 |
| 2-2 | Move-DbaRegServerGroup.ps1 | `public/Move-DbaRegServerGroup.ps1` | processブロック（97-139行目）がメイン処理 |

**主要処理フロー**:
1. **93-95行目**: SqlInstance指定時はGroupパラメータ必須チェック
2. **100-102行目**: SqlInstance指定時はGet-DbaRegServerGroupを呼び出してInputObjectに追加
3. **104行目**: ServerGroupループ開始
4. **105行目**: Get-RegServerParentで親サーバー取得
5. **113-117行目**: NewGroupがDefaultか否かで移動先グループを取得
6. **121-123行目**: 移動先グループが存在しない場合はエラー
7. **125-136行目**: ShouldProcess確認後、ScriptMoveでSQL生成・ExecuteNonQueryで実行
8. **132行目**: 移動後のグループを取得して出力
9. **133行目**: 接続を切断

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaRegServerGroup.ps1 | `public/Get-DbaRegServerGroup.ps1` | ServerGroupオブジェクトの取得方法 |
| 3-2 | Get-RegServerParent | `private/functions/Get-RegServerParent.ps1` | 親サーバー接続の取得方法 |
| 3-3 | Get-RegServerGroupReverseParse | `private/functions/Get-RegServerGroupReverseParse.ps1` | グループパスの逆解析 |

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

```
Move-DbaRegServerGroup
    │
    ├─ Test-Bound (パラメータチェック)
    │
    ├─ Test-FunctionInterrupt (中断チェック)
    │
    ├─ Get-DbaRegServerGroup (SqlInstance指定時)
    │
    ├─ Get-RegServerParent
    │      └─ 親ServerConnection取得
    │
    ├─ Get-DbaRegServerGroup (移動先グループ取得)
    │
    ├─ Get-RegServerGroupReverseParse
    │      └─ グループパス生成
    │
    ├─ ScriptMove().GetScript()
    │      └─ 移動SQL生成
    │
    ├─ ExecuteNonQuery
    │      └─ SQL実行
    │
    └─ Get-DbaRegServerGroup (結果取得)
```

### データフロー図

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

SqlInstance + Group ───▶ Get-DbaRegServerGroup ───▶ ServerGroup
       or                        │
InputObject (pipeline) ──────────┘
                                 │
                                 ▼
                        Get-RegServerParent
                                 │
                                 ▼
                    移動先グループ存在確認
                                 │
                                 ▼
                      ScriptMove + ExecuteNonQuery
                                 │
                                 ▼
                    Get-DbaRegServerGroup ────▶ Moved ServerGroup Object
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Move-DbaRegServerGroup.ps1 | `public/Move-DbaRegServerGroup.ps1` | ソース | 本機能のメイン実装 |
| Get-DbaRegServerGroup.ps1 | `public/Get-DbaRegServerGroup.ps1` | ソース | ServerGroupオブジェクト取得 |
| Get-RegServerParent.ps1 | `private/functions/Get-RegServerParent.ps1` | ソース | 親サーバー接続取得 |
| Get-RegServerGroupReverseParse.ps1 | `private/functions/Get-RegServerGroupReverseParse.ps1` | ソース | グループパス逆解析 |
| Stop-Function.ps1 | `private/functions/Stop-Function.ps1` | ソース | エラーハンドリング |
| Test-Bound.ps1 | `private/functions/Test-Bound.ps1` | ソース | パラメータバインドチェック |
