# 機能設計書 453-New-DbaReplSubscription

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける`New-DbaReplSubscription`関数の機能設計を定義する。この関数はSQL Serverレプリケーションのサブスクリプションを作成し、パブリッシャーからサブスクライバーへのデータ配布経路を確立する。

### 本機能の処理概要

**業務上の目的・背景**：SQL Serverレプリケーションにおいて、サブスクリプションはパブリッシャーから配布されるデータをサブスクライバーが受信するための設定である。本関数は、Push/Pullサブスクリプションの作成を自動化し、複数のサブスクライバーへの一括設定を可能にする。これにより、大規模なレプリケーション構成の展開を効率化できる。

**機能の利用シーン**：
- 複数のサブスクライバーへのレプリケーション一括設定時
- 災害復旧環境でのサブスクリプション自動構成時
- CI/CD パイプラインでのレプリケーション自動化時
- 既存パブリケーションへの新規サブスクライバー追加時

**主要な処理内容**：
1. パブリッシャーへの接続とパブリケーション情報の取得
2. サブスクライバーデータベースの存在確認（存在しない場合は自動作成）
3. 必要なスキーマの作成（dbo以外のスキーマがある場合）
4. パブリケーションタイプに応じたサブスクリプションオブジェクトの作成
5. Push/Pull属性の設定とサブスクリプションの作成

**関連システム・外部連携**：SQL Server Replication Management Objects (RMO)、ディストリビューター、SQL Server Agent（Distribution Agent）

**権限による制御**：パブリッシャーとサブスクライバー両方でsysadminまたはdb_owner権限が必要。サブスクリプションデータベースの作成権限も必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | SQL Server Management Studio - 新しいサブスクリプションウィザード | 参照画面 | サブスクリプション作成処理に相当 |
| N/A | SQL Server Management Studio - レプリケーションモニター | 結果表示画面 | 作成されたサブスクリプションの監視 |

## 機能種別

CRUD操作（Create） / レプリケーション構成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter | Yes | パブリッシャーSQL Serverインスタンス | パイプライン入力対応 |
| SqlCredential | PSCredential | No | パブリッシャー接続用資格情報 | 有効な認証情報 |
| Database | String | No | パブリケーションデータベース名 | 存在するデータベース |
| SubscriberSqlInstance | DbaInstanceParameter[] | Yes | サブスクライバーSQL Serverインスタンス | 複数インスタンス対応 |
| SubscriberSqlCredential | PSCredential | No | サブスクライバー接続用資格情報 | 有効な認証情報 |
| SubscriptionDatabase | String | No | サブスクリプションデータベース名 | 存在しない場合は自動作成 |
| PublicationName | String | Yes | 対象パブリケーション名 | 存在するパブリケーション |
| SubscriptionSqlCredential | PSCredential | No | 同期エージェント用SQL認証情報 | 有効な認証情報 |
| Type | String | Yes | サブスクリプションタイプ（Push/Pull） | ValidateSet検証 |
| EnableException | Switch | No | 例外を有効化 | なし |

### 入力データソース

- パラメータ入力
- パブリッシャーのパブリケーション情報
- サブスクライバーのデータベース情報

## 出力仕様

### 出力データ

本関数は出力オブジェクトを返さない（None）。作成結果の確認には`Get-DbaReplSubscription`を使用する。

### 出力先

パイプライン出力なし。処理結果はWrite-Messageによるログ出力のみ。

## 処理フロー

### 処理シーケンス

```
1. パブリッシャー接続とパブリケーション取得
   ├─ Get-DbaReplServerでパブリッシャー接続
   └─ Get-DbaReplPublicationでパブリケーション情報取得
2. 各サブスクライバーに対する処理（foreach）
   ├─ Get-DbaReplServerでサブスクライバー接続
   └─ サブスクリプションデータベース確認/作成
       └─ 存在しない場合はNew-DbaDatabaseで作成
3. スキーマ確認/作成
   └─ アーティクルのDestinationObjectOwnerのスキーマが存在しない場合は作成
4. パブリケーションタイプ別処理
   ├─ Transactional/Snapshot
   │   ├─ TransPublicationオブジェクトで設定
   │   ├─ AllowPush/AllowPull属性の設定
   │   ├─ TransSubscriptionオブジェクト作成
   │   └─ Create()実行
   └─ Merge
       ├─ MergePublicationオブジェクトで設定
       ├─ AllowPush/AllowPull属性の設定
       ├─ MergeSubscription/MergePullSubscriptionオブジェクト作成
       └─ Create()実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Get-DbaReplServer パブリッシャー]
    B --> C[Get-DbaReplPublication]
    C --> D{パブリケーション存在?}
    D -->|No| E[エラー終了]
    D -->|Yes| F[foreach SubscriberSqlInstance]
    F --> G[Get-DbaReplServer サブスクライバー]
    G --> H{サブスクリプションDB存在?}
    H -->|No| I[New-DbaDatabase]
    H -->|Yes| J[スキーマ確認]
    I --> J
    J --> K{必要なスキーマ存在?}
    K -->|No| L[New-DbaDbSchema]
    K -->|Yes| M{Type判定}
    L --> M
    M -->|Transactional/Snapshot| N[TransPublication設定]
    N --> O{Push/Pull?}
    O -->|Push| P[AllowPush属性設定]
    O -->|Pull| Q[AllowPull属性設定]
    P --> R[TransSubscription作成]
    Q --> R
    M -->|Merge| S[MergePublication設定]
    S --> T{Push/Pull?}
    T -->|Push| U[MergeSubscription作成]
    T -->|Pull| V[MergePullSubscription作成]
    R --> W[次のサブスクライバー]
    U --> W
    V --> W
    W --> F
    F -->|完了| X[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | サブスクリプションDB自動作成 | 存在しない場合は自動的にデータベースを作成 | SubscriptionDatabase未存在時 |
| BR-002 | スキーマ自動作成 | dbo以外の必要なスキーマを自動作成 | アーティクルのDestinationObjectOwnerがdbo以外 |
| BR-003 | パブリケーション属性設定 | Push/Pullに応じてパブリケーションの許可属性を設定 | AllowPush/AllowPullが未設定の場合 |
| BR-004 | 複数サブスクライバー対応 | SubscriberSqlInstanceは配列で複数指定可能 | 常時適用 |

### 計算ロジック

AllowPush/AllowPull属性のビット演算による設定:
- `-band`（ビットAND）で現在の状態を確認
- `-bor`（ビットOR）で新しい属性を追加

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| サブスクリプション作成 | MSsubscriptions | INSERT | サブスクリプション情報の登録 |
| データベース作成 | master.sys.databases | INSERT | サブスクリプションDBの作成（存在しない場合） |
| スキーマ作成 | sys.schemas | INSERT | 必要なスキーマの作成 |

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

#### MSsubscriptions (distribution database)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | subscriber_db | SubscriptionDatabase | サブスクライバーDB名 |
| INSERT | subscriber_name | SubscriberSqlInstance | サブスクライバーサーバー名 |
| INSERT | publication_name | PublicationName | パブリケーション名 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ConnectionError | パブリッシャー/サブスクライバー接続失敗 | 接続パラメータ確認 |
| N/A | パブリケーション不存在 | 指定パブリケーションが見つからない | 正しいパブリケーション名を指定 |
| N/A | データベース作成失敗 | サブスクリプションDB作成に失敗 | 権限確認 |

### リトライ仕様

本関数にリトライ機能は実装されていない。

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

各サブスクライバーへのサブスクリプション作成は個別トランザクションで実行。一つのサブスクライバーでエラーが発生しても、他のサブスクライバーへの処理は継続される（-Continueによる継続処理）。

## パフォーマンス要件

サブスクリプション作成は通常数秒で完了。サブスクリプションデータベースの新規作成が必要な場合は追加時間がかかる。

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

- パブリッシャー/サブスクライバー両方でsysadminまたはdb_owner権限が必要
- SubscriptionSqlCredentialは同期エージェントのSQL認証に使用
- SecureSqlStandardPasswordを使用してパスワードを安全に処理
- Windowsアカウントの使用を推奨（既定動作）

## 備考

- Pull サブスクリプションは現在PUSH として作成される問題がある（TODO: 206行目）
- SynchronizationAgentProcessSecurityの設定は未実装（TODO）
- CreateSyncAgentByDefaultの設定は未実装
- Get-DbaReplSubscriptionによる結果取得は未実装（TODO: 327行目）

---

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

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

### 推奨読解順序

#### Step 1: 関数構造とパラメータを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | param()ブロック（106-124行目） |

**読解のコツ**: `[Parameter(Mandatory, ValueFromPipeline)]`がパイプライン対応の必須パラメータ。`[DbaInstanceParameter[]]`は複数インスタンス対応。

#### Step 2: 初期化処理（beginブロック）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | beginブロック（125-140行目） |

**主要処理フロー**:
1. **130行目**: `Get-DbaReplServer`でパブリッシャー接続
2. **136行目**: `Get-DbaReplPublication`でパブリケーション取得

#### Step 3: サブスクライバー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | processブロック（142-328行目） |

**主要処理フロー**:
- **145行目**: foreachでサブスクライバーをループ
- **150行目**: Get-DbaDatabaseでサブスクリプションDB確認
- **156-162行目**: New-DbaDatabaseでDB作成（存在しない場合）
- **174-179行目**: スキーマ確認/作成

#### Step 4: レプリケーションタイプ別処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | Transactional処理（181-251行目） |
| 4-2 | New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | Merge処理（253-318行目） |

**主要処理フロー**:
- **191-204行目**: Push用のAllowPush属性設定
- **205-216行目**: Pull用のAllowPull属性設定（注：TODOあり）
- **219-224行目**: TransSubscriptionオブジェクト設定
- **248行目**: Create()でサブスクリプション作成

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

```
New-DbaReplSubscription
    │
    ├─ [begin] Get-DbaReplServer (パブリッシャー)
    │      └─ Connect-DbaInstance
    │
    ├─ [begin] Get-DbaReplPublication
    │
    ├─ [process] foreach (SubscriberSqlInstance)
    │      │
    │      ├─ Get-DbaReplServer (サブスクライバー)
    │      │
    │      ├─ Get-DbaDatabase
    │      │      └─ 存在しない場合: New-DbaDatabase
    │      │
    │      ├─ Get-DbaDbSchema
    │      │      └─ 存在しない場合: New-DbaDbSchema
    │      │
    │      ├─ [RMO] TransPublication/MergePublication
    │      │      ├─ LoadProperties()
    │      │      ├─ Attributes (AllowPush/AllowPull)
    │      │      └─ CommitPropertyChanges()
    │      │
    │      └─ [RMO] TransSubscription/MergeSubscription
    │             └─ Create()
```

### データフロー図

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

SqlInstance ─────────────────▶ Get-DbaReplServer ────────────────────▶ パブリッシャー接続
PublicationName ─────────────▶ Get-DbaReplPublication ───────────────▶ パブリケーション情報
                                       │
SubscriberSqlInstance ───────▶ Get-DbaReplServer ────────────────────▶ サブスクライバー接続
SubscriptionDatabase ────────▶ Get-DbaDatabase ──────────────────────▶ DB確認/作成
                                       │
                               Get-DbaDbSchema ──────────────────────▶ スキーマ確認/作成
                                       │
Type (Push/Pull) ────────────▶ AllowPush/AllowPull属性設定 ──────────▶ パブリケーション更新
SubscriptionSqlCredential ───▶ SubscriberSecurity設定 ───────────────▶ サブスクリプション作成
                                       │
                               TransSubscription/MergeSubscription ──▶ (出力なし)
                                       Create()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaReplSubscription.ps1 | `public/New-DbaReplSubscription.ps1` | ソース | メイン関数定義 |
| Get-DbaReplServer.ps1 | `public/Get-DbaReplServer.ps1` | ソース | レプリケーションサーバー接続 |
| Get-DbaReplPublication.ps1 | `public/Get-DbaReplPublication.ps1` | ソース | パブリケーション情報取得 |
| New-DbaDatabase.ps1 | `public/New-DbaDatabase.ps1` | ソース | データベース作成 |
| Get-DbaDbSchema.ps1 | `public/Get-DbaDbSchema.ps1` | ソース | スキーマ確認 |
| New-DbaDbSchema.ps1 | `public/New-DbaDbSchema.ps1` | ソース | スキーマ作成 |
