Bylaw.Ecto.Query.Checks.UtcDatetimeNaiveComparisons (bylaw_ecto_query v0.1.0-alpha.1)

Copy Markdown View Source

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 Ecto.Repo.prepare_query/3 setup.

Summary

Functions

validate(operation, query, opts)

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