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

Validates that queries do not use `offset` without `limit`.

Offset without limit skips rows and then returns every remaining row. That can
create an unbounded scan from an arbitrary position, which is usually an
accidental pagination shape.

## Examples

Bad:

    from(Post, as: :post)
    |> order_by([post: p], asc: p.inserted_at)
    |> offset(10_000)

Why this is bad:

The query skips 10,000 rows and then returns every remaining row. That is
usually an accidental unbounded pagination query.

Better:

    from(Post, as: :post)
    |> order_by([post: p], asc: p.inserted_at)
    |> limit(50)
    |> offset(10_000)

Why this is better:

`limit` gives the page a bounded size. Pair this with
`Bylaw.Ecto.Query.Checks.RequiredOrder` when the page also needs stable row
order.

## Notes

This check only verifies that `offset` has a paired `limit`. It does not prove
the order is deterministic or that offset pagination is the best strategy for
a large table.

## Options

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

The check applies to the root query and nested source subqueries, join
subqueries, CTE queries, combination branches, and expression subqueries.

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