% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/join-tap.R
\name{join_tap}
\alias{join_tap}
\alias{left_join_tap}
\alias{right_join_tap}
\alias{inner_join_tap}
\alias{full_join_tap}
\alias{anti_join_tap}
\alias{semi_join_tap}
\title{Operation-Aware Join Taps}
\usage{
left_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)

right_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)

inner_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)

full_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)

anti_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)

semi_join_tap(
  .data,
  y,
  ...,
  .trail = NULL,
  .label = NULL,
  .stat = NULL,
  .numeric_summary = TRUE,
  .cols_include = NULL,
  .cols_exclude = NULL
)
}
\arguments{
\item{.data}{A data.frame or tibble (left table in the join).}

\item{y}{A data.frame or tibble (right table in the join).}

\item{...}{Arguments passed to the corresponding \verb{dplyr::*_join()} function,
including \code{by}, \code{suffix}, \code{keep}, \code{multiple}, \code{unmatched}, etc. The \code{by}
argument should be passed by name for enriched diagnostics.}

\item{.trail}{An \code{\link[=audit_trail]{audit_trail()}} object, or \code{NULL} (the default). When
\code{NULL}, behavior depends on \code{.stat}: if \code{.stat} is also \code{NULL}, a plain
dplyr join is performed; if \code{.stat} is provided, \code{\link[=validate_join]{validate_join()}}
diagnostics are printed before the join.}

\item{.label}{Optional character label for this snapshot. If \code{NULL},
auto-generated as \code{"left_join_1"} etc.}

\item{.stat}{An unquoted column name for stat tracking, e.g., \code{amount}.
Passed to \code{\link[=validate_join]{validate_join()}}.}

\item{.numeric_summary}{Logical. If \code{FALSE}, skip numeric summary
computation in the snapshot (default \code{TRUE}).}

\item{.cols_include}{Character vector of column names to include in the
snapshot schema, or \code{NULL} (the default) to include all columns. Mutually
exclusive with \code{.cols_exclude}.}

\item{.cols_exclude}{Character vector of column names to exclude from the
snapshot schema, or \code{NULL} (the default). Mutually exclusive with
\code{.cols_include}.}
}
\value{
The joined data.frame or tibble (same as the corresponding
\verb{dplyr::*_join()}).
}
\description{
Performs a dplyr join AND records enriched diagnostics in an audit trail.
These functions replace the pattern of wrapping a join with two
\code{\link[=audit_tap]{audit_tap()}} calls, capturing information that plain taps cannot:
match rates, relationship type, duplicate keys, and unmatched row counts.
}
\details{
Enriched diagnostics (match rates, relationship type, duplicate keys) require
equality joins — \code{by} as a character vector, named character vector, or
simple equality \code{join_by()} expression (e.g., \code{join_by(id)},
\code{join_by(a == b)}). For non-equi \code{join_by()} expressions, the tap records
a basic snapshot without match-rate diagnostics.

All dplyr join features (\code{join_by}, \code{multiple}, \code{unmatched}, \code{suffix}, etc.)
work unchanged via \code{...}.

When \code{.trail} is \code{NULL}:
\itemize{
\item \code{.stat} also \code{NULL}: plain dplyr join
\item \code{.stat} provided: prints \code{\link[=validate_join]{validate_join()}} diagnostics, then joins
\item \code{.label} provided: warns that label is ignored
}
}
\examples{
orders <- data.frame(id = 1:4, amount = c(100, 200, 300, 400))
customers <- data.frame(id = c(2, 3, 5), name = c("A", "B", "C"))

# With trail
trail <- audit_trail("join_example")
result <- orders |>
  audit_tap(trail, "raw") |>
  left_join_tap(customers, by = "id", .trail = trail, .label = "joined")
print(trail)

# Without trail (plain join)
result2 <- left_join_tap(orders, customers, by = "id")

}
\seealso{
Other operation taps:
\code{\link[=filter_tap]{filter_tap()}}
}
\concept{operation taps}
