# `Bylaw.Ecto.Query.Checks.DuplicateJoins`
[🔗](https://github.com/ryanzidago/bylaw/blob/v0.1.0-alpha.1/lib/bylaw/ecto/query/checks/duplicate_joins.ex#L1)

Validates that a query does not repeat equivalent joins.

Duplicate joins make queries harder to reason about and can multiply rows or
add avoidable database work. This check compares each join by its join kind,
source or association, prefix, hints, source parameters, and normalized `on`
expression. Named bindings are intentionally ignored, because a different
binding name does not change the rows produced by the join.

## Examples

Bad:

    from(Post, as: :post)
    |> join(:inner, [post: p], c in Comment,
      as: :comment,
      on: c.post_id == p.id
    )
    |> join(:inner, [post: p], visible_c in Comment,
      as: :visible_comment,
      on: vc.post_id == p.id
    )

Why this is bad:

The same relationship appears twice. That can multiply rows and make later
predicates ambiguous because each binding represents the same joined source.

Better:

    from(Post, as: :post)
    |> join(:inner, [post: p], c in Comment,
      as: :comment,
      on: c.post_id == p.id
    )
    |> where([comment: c], c.visible == true)

Why this is better:

One join represents the relationship once, and predicates that refine the
joined rows use that binding.

## Notes

This check compares supported Ecto join shapes after normalization. It is not
a semantic SQL equivalence engine.

The check is static and intentionally inspects the query structure produced by
Ecto's query macros. It supports the tested join shapes exposed by the Ecto
query API.

## Options

  * `:validate` - explicit `false` disables the check. Defaults to `true`.

## Usage

Add this module to the explicit check list passed through `Bylaw.Ecto.Query`.
See `Bylaw.Ecto.Query` for the full `c:Ecto.Repo.prepare_query/3` setup.

# `validate`

```elixir
@spec validate(
  Bylaw.Ecto.Query.Check.operation(),
  Bylaw.Ecto.Query.Check.query(),
  opts()
) ::
  Bylaw.Ecto.Query.Check.result()
```

Implements the `Bylaw.Ecto.Query.Check` validation callback.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
