# 機能設計書 23-right_join

## 概要

本ドキュメントは、dplyrパッケージにおける`right_join`関数の機能設計を定義する。`right_join`は、2つのデータフレームを右結合し、右側テーブル（y）のすべての行を保持しながら、左側テーブル（x）から一致する列を追加するMutating Join関数である。

### 本機能の処理概要

`right_join`関数は、SQLの RIGHT OUTER JOIN に相当する操作を実行する。右側のデータフレーム（y）のすべての行を保持し、指定されたキー列に基づいて左側のデータフレーム（x）から一致する行のデータを結合する。xに一致する行がない場合、xの列にはNAが設定される。結果の行順は、まずマッチしたxの行が出力され、その後にyにのみ存在する行が追加される。

**業務上の目的・背景**：参照テーブルを基準として、そこにメインデータの情報を付与したい場合に使用する。例えば、全ての商品カテゴリを基準として、そこに売上情報を付与する場合、カテゴリマスタを右側に配置することで、売上のないカテゴリも含めた分析が可能になる。`left_join`と比較して、どちらのテーブルを基準とするかの違いであり、`right_join(x, y)`は概念的に`left_join(y, x)`に近いが、列の順序やグループ化の継承が異なる。

**機能の利用シーン**：
- 参照マスタを基準とした網羅的なデータ結合
- 右側テーブルの完全性を保証したい場合
- yの行順序を優先したい分析ケース
- SQLのRIGHT JOINとの互換性が必要な場合

**主要な処理内容**：
1. 結合キーの特定（by引数の解析またはcommon columnsの自動検出）
2. キー列の型の共通化（型が異なる場合のキャスト処理）
3. vctrs::vec_locate_matchesによるマッチング処理
4. 結果データフレームの構築（マッチしたx行 + yのみの行、yの列を追加）
5. 重複列名への接尾辞付与
6. 非マッチx行のキー値をyから補完（keep=FALSEの場合）

**関連システム・外部連携**：vctrパッケージのvec_locate_matches関数を使用してマッチング処理を実行。rlangパッケージによるNSE処理、tibbleパッケージとの相互運用性を提供。

**権限による制御**：特になし。Rの通常のオブジェクト操作権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはRライブラリであり、UIは存在しない |

## 機能種別

データ変換 / 結合処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | data.frame / tibble | Yes | 左側テーブル | data.frameまたはその拡張型 |
| y | data.frame / tibble | Yes | 右側（基準）テーブル | data.frameまたはその拡張型 |
| by | join_by / character / NULL | No | 結合キーの指定 | join_by()、文字ベクトル、またはNULL |
| copy | logical | No | 異なるソース間でのコピー許可 | TRUE/FALSE（デフォルト: FALSE） |
| suffix | character(2) | No | 重複列名への接尾辞 | 長さ2の文字ベクトル（デフォルト: c(".x", ".y")） |
| keep | logical / NULL | No | 両テーブルのキー列を保持するか | TRUE/FALSE/NULL |
| na_matches | character | No | NAの一致方法 | "na"（デフォルト）または"never" |
| multiple | character | No | 複数マッチの処理方法 | "all", "any", "first", "last" |
| unmatched | character | No | 非マッチ行の処理 | "drop"または"error" |
| relationship | character / NULL | No | 期待される関係性 | "one-to-one", "one-to-many", "many-to-one", "many-to-many", NULL |

### 入力データソース

R環境内のdata.frame、tibble、またはdbplyr/dtplyrによるリモートテーブル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | data.frame / tibble | xと同じ型で、yの全行を含む結合結果 |

### 出力先

R環境内のオブジェクトとして返却

## 処理フロー

### 処理シーケンス

```
1. 引数の検証
   └─ check_dots_empty0: 不正な追加引数のチェック
2. データソースの同期
   └─ auto_copy: 異なるソースの場合のコピー処理
3. join_mutate関数への委譲（type="right"）
   ├─ na_matchesの検証
   ├─ keepの検証
   ├─ by引数の解析（join_by_commonまたはas_join_by）
   ├─ join_cols: 出力列の決定
   ├─ join_cast_common: キー列の型統一
   ├─ join_rows: マッチング処理
   ├─ 結果の構築（マッチしたx行 + yのみの行）
   └─ keep=FALSE時：非マッチ行のキー値をyから補完
4. dplyr_reconstruct: 出力型の復元
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[check_dots_empty0]
    B --> C[auto_copy: yをxのソースにコピー]
    C --> D[join_mutate呼び出し type=right]
    D --> E[na_matches/keep検証]
    E --> F{by指定あり?}
    F -->|No| G[join_by_common: 共通列検出]
    F -->|Yes| H[as_join_by: by解析]
    G --> I[join_cols: 出力列計算]
    H --> I
    I --> J[join_cast_common: 型統一]
    J --> K[join_rows: マッチング]
    K --> L[結果データフレーム構築]
    L --> M{keep=FALSE かつ NA行あり?}
    M -->|Yes| N[yからキー値を補完]
    M -->|No| O[dplyr_reconstruct]
    N --> O
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | 右テーブル保持 | yのすべての行を結果に含める | 常に適用 |
| BR-23-02 | 非マッチNA | xに一致しない行はxの列がNAになる | 常に適用 |
| BR-23-03 | 行順序 | マッチしたx行が先、yのみの行が後 | 常に適用 |
| BR-23-04 | キー値補完 | keep=FALSE時、非マッチ行のキー値をyから補完 | keep=FALSE/NULL時 |
| BR-23-05 | 多対多警告 | 等価結合で多対多関係を検出時に警告 | relationship=NULL時 |

### 計算ロジック

- **マッチング**: vctrs::vec_locate_matchesを使用
- **行インデックス**: マッチしない行はNA、マッチする行は対応するxのインデックス
- **キー値マージ**: keep=FALSE時、出力キー列はxからマッチ行、yから非マッチ行の値を使用

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

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

本機能はインメモリ処理のため、データベース操作は発生しない。ただし、dbplyrバックエンドと連携した場合、SQLのRIGHT JOINクエリが生成される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| dplyr_error_join | 結合エラー | キー列の型が互換性なし | 同じ型に変換するか結合キーを見直す |
| dplyr_error_join_matches_nothing | 非マッチエラー | unmatched="error"でxに非マッチ行あり | 非マッチ行を確認するかunmatched="drop"に変更 |
| dplyr_error_join_relationship | 関係性エラー | relationship指定に違反 | データの関係性を確認 |

### リトライ仕様

該当なし（同期処理）

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

該当なし（インメモリ処理）

## パフォーマンス要件

- 計算量: O(n + m) ～ O(n * m)（nはxの行数、mはyの行数、マッチングパターンに依存）
- メモリ使用量: 最大で結果行数分のメモリを消費

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

特になし。入力データの機密性は呼び出し側の責任で管理する。

## 備考

- `right_join(x, y)`は`left_join(y, x)[, c(names(x), setdiff(names(y), names(x)))]`に近いが、グループ化やデータフレーム型の継承が異なる
- xのグループ化は結果に継承されるが、xに存在しない行のグループは適切に処理される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | join-by.R | `R/join-by.R` | join_by関数とdplyr_join_byクラスの構造 |
| 1-2 | join.R | `R/join.R` | Mutating Joinsのドキュメント（1-247行目） |

**読解のコツ**: right_joinはleft_joinとほぼ同じ構造で、type="right"が渡される点が異なる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | join.R | `R/join.R` | right_join関数本体（343-385行目） |

**主要処理フロー**:
1. **343-353行目**: right_joinジェネリック関数定義
2. **357-369行目**: right_join.data.frameメソッドのパラメータ定義
3. **370行目**: check_dots_empty0
4. **371行目**: auto_copy
5. **372-384行目**: join_mutate呼び出し - type="right"を指定

#### Step 3: 結合コア処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | join.R | `R/join.R` | join_mutate関数（687-802行目） |
| 3-2 | join.R | `R/join.R` | キー値補完処理（791-798行目）- right/full join固有 |

**主要処理フロー**:
- **791行目**: `type == "right" || type == "full"` の条件分岐
- **794-797行目**: NAのx行に対してyからキー値を補完

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

```
right_join(x, y, by, copy, suffix, keep, na_matches, multiple, unmatched, relationship)
    │
    ├─ check_dots_empty0(...)
    │
    ├─ auto_copy(x, y, copy)
    │
    └─ join_mutate(x, y, by, type="right", ...)
           │
           ├─ join_cols(x_names, y_names, by, suffix, keep)
           │
           ├─ join_cast_common(x_key, y_key, vars)
           │
           ├─ join_rows(x_key, y_key, type="right", ...)
           │      └─ dplyr_locate_matches(...)
           │
           ├─ 結果構築: vec_slice(x_out, x_slicer), vec_slice(y_out, y_slicer)
           │
           ├─ keep=FALSE時: 非マッチ行のキー値をyから補完
           │
           └─ dplyr_reconstruct(out, x)
```

### データフロー図

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

x (data.frame) ──┐
                 ├─▶ join_rows(type="right") ─▶ マッチング
y (data.frame) ──┤           │
                 │           ├─▶ マッチしたx行のインデックス
                 │           └─▶ yの全行インデックス
                 │
                 └─▶ キー値補完（keep=FALSE時）
                           │
                           └─▶ xのNA行にyのキー値を設定
                                    │
                                    └─▶ 結合結果 (data.frame)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| join.R | `R/join.R` | ソース | right_join関数の定義 |
| join-rows.R | `R/join-rows.R` | ソース | join_rows関数の定義 |
| join-cols.R | `R/join-cols.R` | ソース | join_cols関数の定義 |
| join-by.R | `R/join-by.R` | ソース | join_by関数の定義 |
