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

Validates that queries do not use explicit cartesian joins.

This check catches join shapes that are easy to introduce accidentally and
expensive to run.

## Examples

Bad:

    from(Post, as: :post)
    |> join(:inner, [post: p], c in Comment,
      as: :comment,
      on: true
    )

Why this is bad:

`on: true` creates every possible pair of posts and comments. That can
multiply rows, inflate aggregates, and produce a query that is much more
expensive than intended.

Better:

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

Why this is better:

The join predicate states the relationship between the two tables, so each
joined row is tied back to its post.

Bad:

    from(Plan, as: :plan)
    |> join(:cross, [plan: pl], f in Feature, as: :feature)
    |> where([feature: f], f.enabled == true)

## Notes

This check catches obvious cartesian joins: `cross_join`, uncorrelated
`cross_lateral_join`, and non-association joins whose `on` expression is
literally `true`. It does not parse SQL fragments or prove general SQL
cardinality.

It rejects `cross_join`, uncorrelated `cross_lateral_join`, and
non-association joins whose `on` expression is literally `true`. Correlated
lateral joins are treated as constrained when a supported subquery predicate
depends on both a local subquery binding and a previous parent binding, or
when a lateral fragment source exposes a previous parent binding reference.

## Options

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

Like Bylaw's other Ecto query checks, this intentionally inspects the query
structure produced by Ecto's query macros. It supports the tested join and
lateral subquery shapes exposed by the Ecto query API. Association joins are
not considered literal `on: true` joins because Ecto stores their association
predicate separately from the `on` expression.

This check is a guardrail for obvious cartesian joins, not a full SQL
cardinality proof. It does not parse fragment SQL. For lateral fragments, an
Ecto-visible reference to a previous binding is treated as dependency
evidence; opaque SQL that needs stricter review should be handled in the
application query or by disabling the check for that call site.

## 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*
