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

Validates that root UTC datetime fields are not compared to `NaiveDateTime` values.

This catches queries where a field backed by `:utc_datetime` or
`:utc_datetime_usec` is compared to a `NaiveDateTime` value.

## Examples

Bad:

    naive_datetime = ~N[2026-01-01 00:00:00]

    from(Event, as: :event)
    |> where([event: e], e.inserted_at >= ^naive_datetime)

Why this is bad:

Ecto may be able to cast many values, but a naive datetime does not say what
timezone the value meant. Callers should convert the value to a `DateTime`
before building the query so the timezone decision is explicit.

Better:

    datetime = DateTime.from_naive!(naive_datetime, "Etc/UTC")

    from(Event, as: :event)
    |> where([event: e], e.inserted_at >= ^datetime)

Why this is better:

The comparison value is an explicit UTC datetime, so the instant being queried
does not depend on an implicit timezone assumption.

## Notes

This check inspects supported root UTC datetime field comparisons and `in`
predicates. It ignores non-root bindings, fragments that hide field access,
subqueries, and schema-less queries without configured fields.

## Options

  * `:validate` - explicit `false` disables the check. Defaults to `true`.
  * `:fields` - optional non-empty list of root fields to validate. When
    omitted, the check validates UTC datetime fields reflected from the root
    Ecto schema.

Example check spec:

    {Bylaw.Ecto.Query.Checks.UtcDatetimeNaiveComparisons,
     fields: [:inserted_at, :updated_at]}

The check inspects direct root field comparisons and `in` predicates in
`where` expressions. It detects visible `NaiveDateTime` values in pinned
parameters, pinned lists, `type(^param, type)` wrappers, and supported raw
query maps. It ignores field-to-field comparisons, non-root bindings,
fragments that hide field access, subqueries, and schema-less queries without
configured fields.

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