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

Copy Markdown View Source

Validates that root temporal interval predicates are half-open.

Half-open temporal intervals include the start boundary and exclude the end boundary.

Examples

Bad:

from(Event, as: :event)
|> where([event: e], e.occurred_at > ^start_at)
|> where([event: e], e.occurred_at <= ^end_at)

Why this is bad:

The query excludes events exactly at start_at and includes events exactly at end_at. Adjacent windows built this way leave a gap at the start boundary and can double-count rows at the end boundary.

Better:

from(Event, as: :event)
|> where([event: e], e.occurred_at >= ^start_at)
|> where([event: e], e.occurred_at < ^end_at)

Why this is better:

The query uses a half-open interval, [start_at, end_at). Adjacent windows compose without gaps or overlap because each boundary value belongs to exactly one window.

Notes

This check inspects direct root temporal field comparisons in where expressions. It does not prove interval correctness when boundaries are hidden inside fragments, non-root bindings, subqueries, or field-to-field comparisons.

This catches the common off-by-one interval boundary shapes > for a lower bound and <= for an upper bound on root temporal 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 temporal fields reflected from the root Ecto schema.

Example check spec:

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

The check is static. It inspects direct root field comparisons in where expressions and ignores field-to-field comparisons, non-root bindings, fragments that hide field access, 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.