# 機能設計書 85-Export-DbaScript

## 概要

本ドキュメントは、dbatools PowerShellモジュールのExport-DbaScript関数の機能設計を定義する。この関数は、SQL Server Management Objects（SMO）からT-SQL CREATE スクリプトを生成し、マイグレーションやデプロイメント用のスクリプトファイルを作成する機能を提供する。

### 本機能の処理概要

Export-DbaScript は、dbatoolsコマンドから取得したSMOオブジェクト（テーブル、ジョブ、ログイン、ストアドプロシージャなど）を、実行可能なT-SQL CREATEスクリプトに変換するコマンドレットである。バッチセパレーターの適切なフォーマット設定と、カスタムスクリプティングオプションをサポートする。

**業務上の目的・背景**：データベースオブジェクトのスクリプト化は、環境間のマイグレーション、設定のバックアップ、デプロイメントスクリプトの作成、SQL Server構成のドキュメント化など、多くの運用シナリオで必要とされる。本機能は、手動スクリプティングなしでSQL Serverオブジェクトのスクリプトを生成し、複数のオブジェクトを統合デプロイメントスクリプトとして結合する機能を提供する。

**機能の利用シーン**：
- 開発環境から本番環境へのオブジェクトマイグレーション
- SQLエージェントジョブのバックアップと別サーバーへの展開
- データベースオブジェクトの変更履歴管理（ソース管理連携）
- 災害復旧用のサーバー構成ドキュメント化
- ログインとセキュリティ設定のスクリプト化
- CI/CDパイプラインでのデプロイメントスクリプト生成

**主要な処理内容**：
1. パイプラインからSMOオブジェクトの受け取り
2. オブジェクトタイプの検証（SMOオブジェクトであることの確認）
3. SMO Scripterオブジェクトの作成とオプション設定
4. スクリプトの生成（EnumScriptメソッド使用）
5. バッチセパレーターの追加
6. ファイルへの出力またはパイプラインへの文字列出力

**関連システム・外部連携**：
- SQL Server Management Objects (SMO) ライブラリ
- dbatools の各種Get-コマンド（Get-DbaAgentJob、Get-DbaLogin等）
- ファイルシステムへのスクリプトファイル出力

**権限による制御**：
- スクリプト化するオブジェクトへの読み取り権限が必要
- 一部のオブジェクト（LinkedServer、Credential、Login）ではパスワード情報はスクリプトに含まれない
- ファイル出力時は出力先への書き込み権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 216 | スクリプトエクスポート | 主機能 | オブジェクトのスクリプトエクスポート |

## 機能種別

スクリプト生成 / データエクスポート

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| InputObject | object[] | Yes | スクリプト化するSMOオブジェクト | パイプライン入力対応、SMOオブジェクト必須 |
| ScriptingOptionsObject | Microsoft.SqlServer.Management.Smo.ScriptingOptions | No | カスタムスクリプティングオプション | New-DbaScriptingOptionで作成 |
| Path | string | No | 出力ディレクトリパス | デフォルト: dbatools設定パス |
| FilePath | string | No | 出力ファイルのフルパス | Pathより優先 |
| Encoding | string | No | ファイルエンコーディング | ASCII/BigEndianUnicode/Byte/String/Unicode/UTF7/UTF8/Unknown |
| BatchSeparator | string | No | バッチ区切り文字 | デフォルト: dbatools設定のGO |
| NoPrefix | switch | No | ヘッダーコメントの抑制 | - |
| Passthru | switch | No | 文字列としてパイプライン出力 | - |
| NoClobber | switch | No | 上書き禁止 | - |
| Append | switch | No | 既存ファイルへの追記 | - |
| EnableException | switch | No | 例外処理の有効化 | - |

### 入力データソース

- パイプライン入力: Get-DbaAgentJob、Get-DbaLogin、Get-DbaDatabase 等の出力SMOオブジェクト
- 直接指定: InputObjectパラメータへのSMOオブジェクト配列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| （Passthru時）| string | 生成されたT-SQLスクリプト文字列 |
| （ファイル出力時）| System.IO.FileInfo | 出力されたスクリプトファイルの情報 |

FileInfoプロパティ:
- Name: ファイル名（例: sql2016-Export-DbaScript-20231215_143022.sql）
- FullName: フルパス
- Directory: ディレクトリオブジェクト
- CreationTime: 作成日時
- LastWriteTime: 更新日時
- Length: ファイルサイズ（バイト）
- Extension: 拡張子（.sql）

### 出力先

- ファイルシステム: 指定されたPath/FilePathにSQLスクリプトファイル
- パイプライン: System.IO.FileInfoオブジェクト（Passthru時は文字列）

## 処理フロー

### 処理シーケンス

```
1. 前処理（begin）
   ├─ 出力ディレクトリの検証
   ├─ 実行ユーザー名の取得
   └─ ScriptingOptionsObjectの設定保存

2. 各オブジェクトの処理（process）
   ├─ オブジェクトタイプの検証（SMOチェック）
   ├─ 特殊オブジェクト警告（LinkedServer、Credential、Login）
   ├─ サーバーオブジェクトの取得
   ├─ Scripterオブジェクトの作成
   ├─ プレフィックス（ヘッダー）の生成・出力
   ├─ スクリプトの生成（EnumScript）
   └─ バッチセパレーター付きでファイル/パイプライン出力

3. クリーンアップ
   └─ ScriptingOptionsObject設定の復元
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[出力ディレクトリ検証]
    B --> C[オブジェクトループ開始]
    C --> D{SMOオブジェクト?}
    D -->|No| E[エラー出力、次へ]
    D -->|Yes| F{特殊オブジェクト?}
    F -->|Yes| G[警告出力]
    F -->|No| H[サーバーオブジェクト取得]
    G --> H
    H --> I[Scripter作成]
    I --> J{NoPrefix?}
    J -->|No| K[プレフィックス生成]
    J -->|Yes| L[プレフィックスなし]
    K --> M{Passthru?}
    L --> M
    M -->|Yes| N[文字列出力]
    M -->|No| O[ファイル出力]
    N --> P[EnumScript実行]
    O --> P
    P --> Q[バッチセパレーター追加]
    Q --> R{Passthru?}
    R -->|Yes| S[文字列として出力]
    R -->|No| T[ファイルに書き込み]
    S --> U[次のオブジェクト]
    T --> V[FileInfo出力]
    V --> U
    E --> U
    U --> W{残りオブジェクト?}
    W -->|Yes| C
    W -->|No| X[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | SMOオブジェクト必須 | 入力はMicrosoft.SqlServer.*型のみ | 常時 |
| BR-002 | パスワード非出力 | LinkedServer、Credential、Loginのパスワードはスクリプトに含まない | 対象オブジェクトタイプ時 |
| BR-003 | プレフィックス自動生成 | 作成者、日時、dbatools情報をコメントとして追加 | NoPrefix未指定時 |
| BR-004 | Append時の動作 | 同一ファイルへの追記時はプレフィックス出力をスキップ | Append且つ2つ目以降 |
| BR-005 | AGスクリプト回避策 | AvailabilityGroupオブジェクトは事前に.Script()を呼び出す | AvailabilityGroup型時 |

### 計算ロジック

ファイル名パターン（FilePathが未指定の場合）:
- `{ServerName}-Export-DbaScript-{Timestamp}.sql`

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

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

本機能はデータベースへの変更を行わない。SMOオブジェクトからスクリプトを生成する読み取り専用操作。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvalidData | 型エラー | 入力がSMOオブジェクトでない | SMOオブジェクトを入力 |
| InvalidData | サーバー取得失敗 | 有効なサーバーオブジェクトが見つからない | オブジェクトの親階層を確認 |
| FileExists | ファイルエラー | NoClobber指定時にファイル存在 | Append使用または別パス指定 |
| ScriptingError | 実行エラー | EnumScript実行失敗 | オブジェクトの状態を確認 |

### リトライ仕様

自動リトライは実装されていない。エラー発生時はStop-Functionで処理を停止し、次のオブジェクトの処理を続行する。

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

読み取り専用操作のため、トランザクション制御は不要。

## パフォーマンス要件

- 大量のオブジェクトをスクリプト化する場合、EnumScript呼び出しに時間がかかる
- ScriptBatchTerminator使用時はファイルI/Oが発生
- Appendモードは複数オブジェクトを1ファイルに統合する際に効率的

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

- LinkedServer、Credential、Loginのパスワードはスクリプトに含まれない（セキュリティ上の制限）
- 生成されたスクリプトにはサーバー構成情報が含まれるため、適切なアクセス制御が必要
- ScriptingOptionsObjectでHashedまたはEncryptedパスワードの出力設定が可能（別途設定必要）

## 備考

- プレフィックスには作成者、dbatools情報、作成日時が含まれる
- BatchSeparatorのデフォルト値はdbatools設定（Formatting.BatchSeparator）から取得
- Passthruを使用するとファイル出力せずに文字列として取得可能

---

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

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

### 推奨読解順序

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

入出力のデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 161-177行目のparam()ブロックで入力パラメータを確認 |
| 1-2 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 351行目でGet-ChildItemによるFileInfo出力を確認 |

**読解のコツ**: Passthru時は文字列、それ以外はFileInfoオブジェクトが出力される。

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

前処理と初期設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 178-206行目のbeginブロック |

**主要処理フロー**:
1. **179行目**: 出力ディレクトリの検証（Test-ExportDirectory）
2. **180-184行目**: 実行ユーザー名の取得（Linux/Mac対応）
3. **194-203行目**: ScriptingOptionsObjectの設定保存（後で復元用）

#### Step 3: オブジェクト検証を理解する

SMOオブジェクトの検証ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 210-237行目のオブジェクト検証 |

**主要処理フロー**:
- **212-218行目**: Microsoft.SqlServer.で始まるタイプかチェック
- **220-222行目**: LinkedServer、Credential、Loginへの警告
- **226-228行目**: Configurationタイプへの警告
- **230-236行目**: AvailabilityGroup用のワークアラウンド

#### Step 4: スクリプト生成処理を理解する

Scripterオブジェクトによるスクリプト生成を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 253-290行目のプレフィックスとファイル出力準備 |
| 4-2 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 292-347行目のスクリプト生成と出力 |

**主要処理フロー**:
- **257行目**: Scripterオブジェクトの作成
- **264行目**: Get-ExportFilePathでファイルパス決定
- **269-273行目**: プレフィックスコメントの生成
- **298-313行目**: Passthru時のスクリプト出力
- **314-346行目**: ファイル出力時のスクリプト書き込み

#### Step 5: ScriptingOptionsの使用を理解する

カスタムScriptingOptionsの適用方法を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | 315-335行目のScriptingOptions使用時の処理 |

**主要処理フロー**:
- **315行目**: ScriptingOptionsObject指定時の分岐
- **316-323行目**: ScriptBatchTerminator使用時のファイル直接出力
- **324-334行目**: BatchSeparator手動追加によるスクリプト構築

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

```
Export-DbaScript
    │
    ├─ Test-ExportDirectory
    │      └─ 出力ディレクトリの検証
    │
    ├─ Get-ExportFilePath
    │      └─ ファイルパスの決定
    │
    ├─ New-Object Microsoft.SqlServer.Management.Smo.Scripter
    │      └─ Scripterオブジェクトの作成
    │
    ├─ $scripter.EnumScript()
    │      └─ T-SQLスクリプトの生成
    │
    ├─ $object.Script() (AvailabilityGroup時)
    │      └─ AGオブジェクトのスクリプト回避策
    │
    └─ Out-File
           └─ スクリプトファイルの出力
```

### データフロー図

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

Get-DbaAgentJob ──┐
                  │
Get-DbaLogin ─────┼──▶ SMOオブジェクト
                  │         │
Get-DbaDatabase ──┘         ▼
                     オブジェクト検証
                            │
                            ▼
                     Scripter作成
                            │
                            ▼
                     EnumScript()
                            │
                            ▼
                   バッチセパレーター追加
                            │
                    ┌───────┴───────┐
                    │   Passthru?   │
                    └───────┬───────┘
                       Yes──┤──No
                         │  │   │
                   文字列◀──┘   ▶ .sqlファイル
                         │           │
                         ▼           ▼
                    パイプライン   FileInfo
                       出力         出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | ソース | メイン関数定義 |
| New-DbaScriptingOption.ps1 | `public/New-DbaScriptingOption.ps1` | ソース | スクリプティングオプション作成 |
| Get-DbaAgentJob.ps1 | `public/Get-DbaAgentJob.ps1` | ソース | 入力元の例（ジョブ取得） |
| Get-DbaLogin.ps1 | `public/Get-DbaLogin.ps1` | ソース | 入力元の例（ログイン取得） |
| Get-DbaDatabase.ps1 | `public/Get-DbaDatabase.ps1` | ソース | 入力元の例（データベース取得） |
| Test-ExportDirectory.ps1 | `private/functions/Test-ExportDirectory.ps1` | ソース | ディレクトリ検証 |
| Get-ExportFilePath.ps1 | `private/functions/Get-ExportFilePath.ps1` | ソース | ファイルパス生成 |
| Stop-Function.ps1 | `private/functions/Stop-Function.ps1` | ソース | エラーハンドリング関数 |
| Write-Message.ps1 | `private/functions/Write-Message.ps1` | ソース | メッセージ出力関数 |
