# 機能設計書 646-Move-DbaDbFile

## 概要

本ドキュメントは、データベースファイルを別のドライブまたはフォルダに移動するdbatools PowerShellコマンド「Move-DbaDbFile」の機能設計書です。

### 本機能の処理概要

Move-DbaDbFileは、SQL Serverデータベースのデータファイルとログファイルを新しい場所に移動し、データベースメタデータを更新するコマンドです。

**業務上の目的・背景**：データベースファイルをより高速なストレージに移動したり、ディスク容量を確保したり、ファイルレイアウトを再編成する必要がある場合があります。通常、これにはデータベースをオフラインにし、ファイルをコピーし、ALTER DATABASEでメタデータを更新するという複数の手順が必要です。本機能により、これらの手順を自動化し、安全かつ効率的にファイル移動を実行できます。

**機能の利用シーン**：
- ストレージ階層の変更（HDD→SSD移行など）
- ディスク容量不足時のファイル再配置
- データとログの分離（I/O最適化）
- サーバー統合/分離時のファイル移動
- ファイルレイアウトの標準化

**主要な処理内容**：
1. データベースのオフライン化（必要に応じてFORCE）
2. ファイルコピー（BITS転送またはCopy-Item、ローカル/リモート対応）
3. ALTER DATABASE MODIFY FILE でメタデータ更新
4. データベースのオンライン化
5. オプションでソースファイル削除

**関連システム・外部連携**：
- SQL Serverインスタンス
- ファイルシステム（ローカル/リモート、UNC共有）

**権限による制御**：対象データベースに対するALTER DATABASE権限、ファイルシステムへのアクセス権限が必要です。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI専用 | 主機能 | コマンドライン実行のみ |

## 機能種別

ファイル操作 / メタデータ更新

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter | Yes | 対象SQL Serverインスタンス | パイプライン対応 |
| SqlCredential | PSCredential | No | SQL Server接続用資格情報 | - |
| Database | string | Yes | 対象データベース名 | システムDB不可 |
| FileType | string | 条件付き | 移動するファイルタイプ（Data/Log/Both） | FileDestinationと併用 |
| FileDestination | string | 条件付き | 移動先ディレクトリ | FileTypeと併用 |
| FileToMove | hashtable | 条件付き | ファイル移動のハッシュテーブル | 論理名→移動先ディレクトリ |
| DeleteAfterMove | switch | No | 移動後にソースファイルを削除 | - |
| FileStructureOnly | switch | No | 現在のファイル構造をハッシュテーブルとして出力 | - |
| Force | switch | No | ROLLBACK IMMEDIATEでオフライン化を強制 | - |
| EnableException | switch | No | エラー時に例外をスロー | - |

### 入力データソース

- パイプライン入力: SqlInstance
- 直接パラメータ指定

## 出力仕様

### 出力データ（FileStructureOnly指定時）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | string | ハッシュテーブル形式のテンプレート文字列 |

### 出力データ（デフォルト）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Instance | string | SQL Serverインスタンス名 |
| Database | string | データベース名 |
| LogicalName | string | ファイルの論理名 |
| Source | string | 移動元のファイルパス |
| Destination | string | 移動先のファイルパス |
| Result | string | 操作結果（"Success"/"Failed"/"Already exists. Skipping"） |
| DatabaseFileMetadata | string | メタデータ更新状態（"Updated"/"N/A"） |
| SourceFileDeleted | bool/string | ソースファイル削除状態（true/false/"N/A"） |

### 出力先

パイプライン出力（PSCustomObject or string）

## 処理フロー

### 処理シーケンス

```
1. パラメータ検証
   ├─ FileType指定時はFileDestination必須
   ├─ FileType, FileToMove, FileStructureOnlyのいずれか必須
   └─ システムDBの拒否

2. データベース接続とファイル情報取得
   ├─ オフラインDBの場合: sys.master_filesから取得
   └─ オンラインDBの場合: Get-DbaDbFileで取得

3. FileStructureOnly指定時
   └─ ハッシュテーブルテンプレートを出力して終了

4. データベースをオフラインに設定
   └─ Set-DbaDbState -Offline（Forceオプション対応）

5. 接続方式の判定
   ├─ ローカル実行: Start-BitsTransferまたはCopy-Item
   └─ リモート実行: PowerShell Remoting または UNC共有

6. 移動先パスのアクセス確認
   └─ Test-DbaPath

7. 各ファイルの移動処理
   ├─ ファイルコピー（BITS or Copy-Item）
   ├─ ACLのコピー
   ├─ ALTER DATABASE MODIFY FILE実行
   └─ DeleteAfterMove時のソースファイル削除

8. データベースをオンラインに復帰
   └─ Set-DbaDbState -Online
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{パラメータ検証}
    B -->|失敗| C[エラー終了]
    B -->|成功| D{システムDB?}
    D -->|Yes| C
    D -->|No| E[Connect-DbaInstance]
    E --> F[ファイル情報取得]
    F --> G{FileStructureOnly?}
    G -->|Yes| H[テンプレート出力]
    H --> I[終了]
    G -->|No| J[Set-DbaDbState -Offline]
    J --> K{オフライン成功?}
    K -->|No| C
    K -->|Yes| L[接続方式判定]
    L --> M[Test-DbaPath]
    M --> N{パスアクセス可能?}
    N -->|No| C
    N -->|Yes| O[ファイルループ]
    O --> P{既存チェック}
    P -->|Already exists| Q[スキップ結果出力]
    P -->|コピー必要| R[ファイルコピー]
    R --> S{コピー成功?}
    S -->|No| T[失敗結果出力]
    S -->|Yes| U[ALTER DATABASE]
    U --> V{DeleteAfterMove?}
    V -->|Yes| W[ソースファイル削除]
    V -->|No| X[成功結果出力]
    W --> X
    Q --> Y{次ファイル?}
    T --> Y
    X --> Y
    Y -->|Yes| O
    Y -->|No| Z[Set-DbaDbState -Online]
    Z --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | システムDB制限 | master, model, msdb, tempdbは移動不可 | 常時 |
| BR-002 | パラメータ排他 | FileType/FileDestination と FileToMove は排他 | 常時 |
| BR-003 | オフライン必須 | ファイル移動前にデータベースをオフラインにする | 常時 |
| BR-004 | ACL保持 | ファイルコピー後に元ファイルのACLを適用 | 常時 |
| BR-005 | 既存スキップ | 移動先に同名ファイルが存在する場合はスキップ | 常時 |
| BR-006 | メタデータ更新 | ファイルコピー成功後にALTER DATABASEでパス更新 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| メタデータ更新 | sys.database_files | ALTER DATABASE | ファイルパスの更新 |

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

#### sys.database_files（メタデータ）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| ALTER DATABASE MODIFY FILE | physical_name | 新しいファイルパス | NAME=論理名で特定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidArgument | FileTypeなしでFileDestination指定 | 両方を指定 |
| - | ValidationError | FileType, FileToMove, FileStructureOnlyすべて未指定 | いずれか1つを指定 |
| - | ValidationError | システムDBを指定 | ユーザーDBを指定 |
| - | ConnectionError | SQL Server接続失敗 | 接続情報を確認 |
| - | OfflineError | オフライン化失敗 | -Force使用または接続を切断 |
| - | PathError | 移動先パスにアクセス不可 | パス存在とSQL Serverサービスアカウント権限を確認 |
| - | CopyError | ファイルコピー失敗 | ディスク容量と権限を確認 |

### リトライ仕様

BITS転送失敗時はCopy-Itemにフォールバック

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

各ファイルの移動とメタデータ更新は独立して実行（ロールバック機能なし）

## パフォーマンス要件

- ファイルサイズに依存
- BITS転送はバックグラウンドで効率的に転送
- 大規模ファイル移動時はダウンタイムを考慮

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

- 対象データベースに対するALTER DATABASE権限が必要
- ファイルシステムへの読み書き権限が必要
- SQL Serverサービスアカウントが移動先にアクセス可能であること
- ShouldProcess対応（WhatIf/Confirm）

## 備考

- ダウンタイムが発生するため、メンテナンスウィンドウでの実行を推奨
- ConfirmImpact = "Medium"

---

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

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

### 推奨読解順序

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

出力オブジェクトの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Move-DbaDbFile.ps1 | `public/Move-DbaDbFile.ps1` | L362-371の出力オブジェクト定義 |

**読解のコツ**: returnObjectは最初にSuccess想定で初期化され、エラー時にプロパティが更新されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Move-DbaDbFile.ps1 | `public/Move-DbaDbFile.ps1` | begin/processブロック全体の流れ |

**主要処理フロー**:
1. **142-146行目**: beginブロックでFileType/FileDestinationの組み合わせ検証
2. **148-159行目**: パラメータ検証とシステムDB拒否
3. **176-190行目**: ファイル情報取得（オフライン/オンライン分岐）
4. **194-201行目**: FileStructureOnly処理
5. **210-225行目**: オフライン化処理
6. **227-278行目**: 接続方式判定（ローカル/リモート/UNC）
7. **280-361行目**: ファイルコピー処理
8. **419-430行目**: オンライン復帰処理

#### Step 3: ファイルコピー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Move-DbaDbFile.ps1 | `public/Move-DbaDbFile.ps1` | L291-360のファイルコピー |

**主要処理フロー**:
- **292-308行目**: ローカルコピー（Start-BitsTransfer → Copy-Itemフォールバック）
- **309-360行目**: リモートコピー（PowerShell Remoting → UNCパスフォールバック）
- **326-327行目**: ACLコピー処理
- **374行目**: ALTER DATABASE MODIFY FILE実行

#### Step 4: 状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Move-DbaDbFile.ps1 | `public/Move-DbaDbFile.ps1` | L210-225, L419-430のDB状態管理 |

**主要処理フロー**:
- **213行目**: Set-DbaDbState -Offline -Force:$Force
- **421行目**: Set-DbaDbState -Online

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

```
Move-DbaDbFile
    │
    ├─ Connect-DbaInstance
    │
    ├─ Get-DbaDbState（現在の状態確認）
    │
    ├─ Get-DbaDbFile / Get-DbaDbPhysicalFile（ファイル情報取得）
    │
    ├─ Set-DbaDbState -Offline（オフライン化）
    │
    ├─ Test-PSRemoting（リモート接続判定）
    │
    ├─ Resolve-DbaNetworkName（ホスト名解決）
    │
    ├─ Test-DbaPath（パスアクセス確認）
    │
    ├─ ファイルコピー
    │      ├─ Start-BitsTransfer（ローカル/リモート）
    │      ├─ Copy-Item（フォールバック）
    │      └─ Invoke-Command2（リモート実行）
    │
    ├─ Get-Acl / Set-Acl（ACLコピー）
    │
    ├─ Server.Query（ALTER DATABASE MODIFY FILE）
    │
    └─ Set-DbaDbState -Online（オンライン復帰）
```

### データフロー図

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

SqlInstance ──────────┐
                      │
Database ─────────────┼──▶ Get-DbaDbFile ────────────┐
                      │                               │
FileType ─────────────┤                               ▼
                      │    ┌──────────────────────────────────┐
FileDestination ──────┤    │ 1. Set-DbaDbState -Offline       │
                      │    │ 2. File Copy (BITS/Copy-Item)    │
FileToMove ───────────┤    │ 3. ALTER DATABASE MODIFY FILE    │
                      │    │ 4. Set-DbaDbState -Online        │
DeleteAfterMove ──────┤    └──────────────────────────────────┘
                      │                               │
Force ────────────────┘                               ▼
                                               PSCustomObject
                                               (Instance,
                                                Database,
                                                LogicalName,
                                                Source,
                                                Destination,
                                                Result,
                                                DatabaseFileMetadata,
                                                SourceFileDeleted)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Move-DbaDbFile.ps1 | `public/Move-DbaDbFile.ps1` | ソース | メインコマンド実装 |
| Set-DbaDbState.ps1 | `public/Set-DbaDbState.ps1` | ソース | DB状態変更 |
| Get-DbaDbFile.ps1 | `public/Get-DbaDbFile.ps1` | ソース | ファイル情報取得 |
| Get-DbaDbPhysicalFile.ps1 | `public/Get-DbaDbPhysicalFile.ps1` | ソース | sys.master_filesからのファイル情報取得 |
| Test-DbaPath.ps1 | `public/Test-DbaPath.ps1` | ソース | SQL Serverからのパスアクセス確認 |
| Test-PSRemoting.ps1 | `private/Test-PSRemoting.ps1` | ソース | PowerShell Remoting可否判定 |
| Invoke-Command2.ps1 | `private/Invoke-Command2.ps1` | ソース | リモートコマンド実行 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
