# joinspy 0.8.3

## Bug fixes

- Safe join wrappers no longer modify the caller's `data.table`. When the right-hand side was a `data.table`, the key-column rename was applied in place; the input is now copied before renaming so the caller's object is left untouched.

## Improvements

- `join_explain()` infers the join type from row counts when `type` is not supplied, and remains robust when the type cannot be determined unambiguously.

## Documentation

- Expanded the vignettes with additional worked examples and guidance.

# joinspy 0.8.2

## Bug fixes

- Logged reports now record duplicate-key counts. Text and JSON logs previously left the count blank because the serializer read a mistyped field name (#1).
- Composite (multi-column) keys with a missing component are now treated as `NA`, matching how joins handle them. This corrects NA counts, duplicate detection, and row-count predictions for composite keys (#3).
- Predicted row counts no longer overflow to `NA` for very large joins; counts are kept as doubles (#4).
- `%||%` is imported from rlang, so the package works on R 4.1 through 4.3 (#2).
- Report printing and `key_check()` treat issue text as data, so braces in column names or values are no longer interpreted by cli (#5).
- `suggest_repairs()` generates valid code for non-syntactic column names using `[[ ]]` indexing (#6).

## Internal

- Key resolution, composite-key construction, column checks, and cardinality classification now share single-source helpers (#7).
- Errors use cli for consistent, classed messages.
- JSON logging escapes backslashes and control characters.

---

# joinspy 0.8.0

## Multi-Backend Join Support

- Join wrappers (`left_join_spy()`, `join_strict()`, etc.) now auto-detect input class and dispatch to the native join engine: tibble inputs use dplyr, data.table inputs use data.table, plain data.frames use base R `merge()`
- New `backend` parameter for explicit override (`"base"`, `"dplyr"`, `"data.table"`)
- Class preserved through the full diagnose-repair-join cycle
- Graceful fallback to base R with a warning if the detected backend package is not installed

## Documentation Overhaul

- README reframed around string-level key diagnostics (whitespace, case, encoding, typos) as the primary value proposition
- Three new vignettes: "Why Your Keys Don't Match" (real-world scenarios), "Joins in Production" (pipelines, logging, guards), "Working with Backends" (tibble/data.table/base R)
- Existing vignettes (quickstart, common-issues) expanded from 850 to 4,500+ prose words

## Testing

- 46 new backend tests covering auto-detection, explicit override, named `by` vectors, class preservation, and all three backends

---

# joinspy 0.7.2

## Testing & Quality

- Improved test coverage from 65% to 94%
- Added comprehensive tests for all exported and internal functions
- Added `.covrignore` to exclude untestable Shiny addin from coverage calculation

---

# joinspy 0.7.1

## API Simplification

- **Removed `plot_venn()`**: Use `plot(report, file = "...")` instead
- **Removed `plot_summary()`**: Use `summary(report, format = "markdown")` instead
- **Enhanced `plot()`**: Now accepts `file`, `width`, `height`, `colors` parameters
- **Enhanced `summary()`**: Now accepts `format` parameter ("data.frame", "text", "markdown")

## CRAN Preparation

- Added `cph` role and ORCID to DESCRIPTION
- Added `Language: en-US` field
- Quoted proper nouns in documentation

---

# joinspy 0.7.0

## Integration & Workflow

- **RStudio addin**: `addin_join_inspector()` opens an interactive Shiny gadget for exploring join diagnostics
- **Logging & audit**: `log_report()` writes reports to file (text/JSON/RDS format)
- **Automatic logging**: `set_log_file()` / `get_log_file()` for session-wide logging configuration
- **Deferred access**: `last_report()` retrieves diagnostics after silent joins
- **Silent mode**: `.quiet = TRUE` parameter for all `*_join_spy()` wrappers

---

# joinspy 0.6.0

## Advanced Join Patterns

- **`check_cartesian()`**: Detect and warn about cross-join / Cartesian product explosions
- **`detect_cardinality()`**: Determine actual key relationship (1:1, 1:n, n:1, n:m)
- **`analyze_join_chain()`**: Analyze cascading joins in multi-table workflows

---

# joinspy 0.5.0

## Visualization

- **`plot_venn()`**: Venn diagram of key overlap with PNG/SVG/PDF export
- **`plot_summary()`**: Summary tables in text, markdown, or data.frame format
- **S3 integration**: `plot()` method for JoinReport objects

---

# joinspy 0.4.0

## Performance & Scale

- **Sampling mode**: `join_spy(x, y, by, sample = 10000)` for large datasets
- **Memory estimation**: Predict join result size before execution
- **Reproducible sampling**: Optional `seed` parameter for consistent results

---

# joinspy 0.3.0

## Auto-Repair

- **`join_repair()`**: Automatically fix common key issues
  - Trim leading/trailing whitespace
  - Standardize case (to lower/upper)
  - Remove invisible characters
  - Convert empty strings to NA
- **`suggest_repairs()`**: Generate R code snippets to fix detected issues
- **Dry-run mode**: Preview changes without modifying data

---

# joinspy 0.2.0

## Enhanced Detection

### Type & Format Issues

- Type coercion warnings (character to factor, numeric-as-string to numeric)
- Factor level mismatches between tables
- Empty string vs NA distinction
- Numeric precision warnings for floating-point keys

### Near-Match Detection

- Fuzzy match candidates (Levenshtein distance ≤ 2)
- Suggested matches for unmatched keys
- Configurable similarity threshold

### Multi-Column Join Analysis

- Per-column breakdown for composite keys
- Problem column identification (lowest match rate)

---

# joinspy 0.1.0

Initial release.

## Core Functions

- `join_spy()` - Comprehensive pre-join diagnostic report
- `key_check()` - Quick key quality assessment
- `key_duplicates()` - Find and locate duplicate keys
- `join_explain()` - Explain row count changes post-join
- `join_diff()` - Before/after state comparison
- `join_strict()` - Join with cardinality enforcement
- `left_join_spy()`, `right_join_spy()`, `inner_join_spy()`, `full_join_spy()` - Join wrappers with diagnostics

## Issue Detection

- Duplicate key detection with row locations
- Whitespace detection (leading/trailing spaces)
- Case mismatch detection
- Encoding issue detection (UTF-8 vs Latin-1, invisible Unicode)
- NA key detection
- Cardinality analysis (1:1, 1:n, n:1, n:m)

## S3 Methods

- `print()`, `summary()`, `plot()` methods for JoinReport objects

## Documentation

- Getting started vignette
- Common issues troubleshooting guide
