Validates that explicit schema joins preserve configured mandatory keys.
This check is intentionally narrow. It handles direct schema joins.
Examples
Bad:
from(Post, as: :post)
|> join(:inner, [post: p], c in Comment,
as: :comment,
on: c.post_id == p.id
)Why this is bad:
If :organization_id is configured as mandatory, the join preserves the row
relationship but not the tenant key. Bad or inconsistent foreign-key data can
cross tenant boundaries.
Better:
from(Post, as: :post)
|> join(:inner, [post: p], c in Comment,
as: :comment,
on:
c.post_id == p.id and
c.organization_id == p.organization_id
)Why this is better:
The join requires both the row relationship and the configured key to match.
Notes
This check only validates direct explicit schema joins and supported equality
predicates in the join on expression. Association joins, subqueries,
fragments, and schema-less joins are ignored.
Association joins, subqueries, fragments, and schema-less joins are not validated by this check.
Like Bylaw's other Ecto query checks, this reads Ecto query structs directly. Ecto treats those structs as opaque, so this check intentionally supports a small, tested subset of Ecto's query AST.
Options
:validate- explicitfalsedisables this check. It can be used in the repo-wide check list or in call-site overrides passed toBylaw.Ecto.Query.validate/4.:rules- optional rule keyword list or non-empty list of rule keyword lists. When omitted, top-level:keysand:matchpreserve the current global behavior for compatibility.:keys- required non-empty list of field names when the check runs.:match-:anyor:all. Defaults to:any.
This check requires :keys, so bare-module configuration is not valid.
Run globally:
{Bylaw.Ecto.Query.Checks.MandatoryJoinKeys,
rules: [keys: [:organization_id]]}Run only for matching rule scopes:
{Bylaw.Ecto.Query.Checks.MandatoryJoinKeys,
rules: [
[where: [ecto_schemas: [Post]], keys: [:organization_id]],
[where: [tables: ["posts"]], keys: [:organization_id]]
]}Require every configured key instead of any one key:
{Bylaw.Ecto.Query.Checks.MandatoryJoinKeys,
rules: [keys: [:organization_id, :account_id], match: :all]}When a join schema does not contain any configured keys, that join is not
applicable and the check returns no issue for it. For applicable joins, the
check accepts direct equality predicates between the joined binding and
another query binding in the join on expression.
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
Implements the Bylaw.Ecto.Query.Check validation callback.
Functions
@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.