# 機能設計書 179-Join-DbaPath

## 概要

本ドキュメントは、dbatools PowerShellモジュールのJoin-DbaPath関数の機能設計を定義する。WindowsとLinux SQL Serverインスタンスの両方に対して正しいパス区切り文字を使用してファイルパスを構築する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：SQL Server on Linuxの登場により、SQL Serverは異なるOSプラットフォームで動作するようになった。この関数は、ターゲットSQL ServerインスタンスのOSに基づいて適切なパス区切り文字（Windowsはバックスラッシュ、Linuxはフォワードスラッシュ）を自動的に使用してファイルパスを構築する。バックアップファイル、エクスポート、スクリプト、またはリモートサーバー上のファイルを参照する必要があるSQL Server操作のパス構築の推測作業を排除する。

**機能の利用シーン**：
- クロスプラットフォーム環境でのバックアップファイルパス構築
- SQL Server on Linuxへのファイル出力パス指定
- マルチプラットフォーム対応のスクリプト作成
- リモートSQL Serverでのディレクトリパス構築

**主要な処理内容**：
1. SqlInstance指定の有無を判定
2. SqlInstance未指定時はローカルマシンのパス区切り規則を使用
3. SqlInstance指定時はTest-HostOSLinuxでリモートOSを判定
4. Linuxの場合はフォワードスラッシュでパス結合
5. Windowsの場合はバックスラッシュでパス結合

**関連システム・外部連携**：SQL Server Management Objects (SMO) を使用してリモートSQL ServerのOS情報を取得。

**権限による制御**：リモートSQL Serverへの接続権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに登録なし |

## 機能種別

ユーティリティ / パス操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Path | string | Yes | ベースディレクトリパス | Mandatory, Position 0 |
| SqlInstance | DbaInstanceParameter | No | ターゲットSQL Serverインスタンス | - |
| Child | string[] | No | 追加のパスセグメント | ValueFromRemainingArguments, Alias: ChildPath |

### 入力データソース

- Pathパラメータで指定されたベースパス
- Childパラメータで指定された追加パスセグメント

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (return) | string | 構築されたファイルパス |

### 出力先

- 標準出力（パイプライン）に文字列を出力

## 処理フロー

### 処理シーケンス

```
1. SqlInstance指定確認
   └─ 未指定の場合: ローカルパス区切り使用

2. ローカルパス処理（SqlInstance未指定時）
   ├─ Path + Child をローカル区切り文字で結合
   └─ 混在する区切り文字を正規化

3. リモートパス処理（SqlInstance指定時）
   ├─ Test-HostOSLinuxでOS判定
   ├─ Linux検出時: / で結合
   └─ Windows検出時: [IO.Path]::Combineで結合

4. パス文字列を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance<br/>指定あり?}
    B -->|No| C[ローカルパス処理]
    B -->|Yes| D[Test-HostOSLinux]
    C --> E[Path + Child を<br/>ローカル区切りで結合]
    E --> F[区切り文字正規化]
    F --> G[パス文字列返却]
    D --> H{Linux?}
    H -->|Yes| I[\ を / に置換]
    I --> J[/ で Child 結合]
    J --> G
    H -->|No| K{PSv6+ Unix?}
    K -->|Yes| L[\ を / に置換]
    K -->|No| M[/ を \ に置換]
    L --> N[[IO.Path]::Combine]
    M --> N
    N --> G
    G --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-179-01 | ローカルデフォルト | SqlInstance未指定時はローカルマシンの規則を使用 | SqlInstance未指定時 |
| BR-179-02 | Linux判定 | Test-HostOSLinuxでリモートOSを判定 | SqlInstance指定時 |
| BR-179-03 | Linux区切り | Linuxの場合は / を使用 | Linux検出時 |
| BR-179-04 | Windows区切り | Windowsの場合は \ を使用 | Windows検出時 |
| BR-179-05 | PSv6+ Unix対応 | PowerShell 6+のUnix環境でも正しく処理 | PSv6+ かつ Unix環境 |

### 計算ロジック

ローカルパス結合:
```powershell
@($path) + $Child -join [IO.Path]::DirectorySeparatorChar -replace '\\|/', [IO.Path]::DirectorySeparatorChar
```

リモートLinuxパス結合:
```powershell
$resultingPath = $resultingPath.Replace("\", "/")
foreach ($childItem in $Child) {
    $resultingPath = ($resultingPath, $childItem) -join '/'
}
```

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConnectionError | SqlInstance接続失敗 | 接続情報を確認 |

### リトライ仕様

リトライ機能なし。

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

トランザクション処理なし。

## パフォーマンス要件

- 軽量なパス操作のため高速
- SqlInstance指定時はリモート接続のオーバーヘッドあり

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

- リモートSQL Serverへの接続権限が必要（SqlInstance指定時）

## 備考

- PowerShell 6+のクロスプラットフォーム対応
- Test-HostOSLinux内部関数に依存

---

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

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

### 推奨読解順序

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

パラメータ構造と戻り値を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Join-DbaPath.ps1 | `public/Join-DbaPath.ps1` | 46-54行目: パラメータ定義 |

**読解のコツ**: ChildパラメータがValueFromRemainingArgumentsであることに注目。可変長引数として機能する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Join-DbaPath.ps1 | `public/Join-DbaPath.ps1` | 関数全体の流れを把握 |

**主要処理フロー**:
1. **56-60行目**: SqlInstance未指定時のローカル処理
2. **62-82行目**: SqlInstance指定時のリモート処理
3. **64-70行目**: Linux検出時の処理
4. **71-80行目**: Windows検出時の処理

#### Step 3: OS判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Join-DbaPath.ps1 | `public/Join-DbaPath.ps1` | 64行目: Test-HostOSLinux呼び出し |

**主要処理フロー**:
- **64行目**: Test-HostOSLinuxでリモートOS判定
- **72行目**: PSVersionTable.PSVersion.Major判定
- **72行目**: $script:isWindows判定

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

```
Join-DbaPath
    │
    ├─ SqlInstance未指定時
    │      ├─ [IO.Path]::DirectorySeparatorChar取得
    │      └─ -join および -replace で結合
    │
    └─ SqlInstance指定時
           ├─ Test-HostOSLinux
           │      └─ リモートOS判定
           │
           ├─ Linux検出時
           │      └─ / でパス結合
           │
           └─ Windows検出時
                  └─ [IO.Path]::Combine
```

### データフロー図

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

Path ─────────────────┐
                      │
Child[] ──────────────┼──▶ SqlInstance判定
                      │           │
SqlInstance ──────────┘           │
                          ┌───────┴───────┐
                          ▼               ▼
                    [未指定]         [指定あり]
                          │               │
                          ▼               ▼
                    ローカル規則    Test-HostOSLinux
                          │               │
                          │       ┌───────┴───────┐
                          │       ▼               ▼
                          │   [Linux]        [Windows]
                          │       │               │
                          │       ▼               ▼
                          │    / 結合       \ 結合
                          │       │               │
                          └───────┴───────────────┘
                                        │
                                        ▼
                                  結合済みパス文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Join-DbaPath.ps1 | `public/Join-DbaPath.ps1` | ソース | メイン関数 |
| Test-HostOSLinux.ps1 | `private/functions/` | ソース | リモートOS判定 |
