Bylaw.Db.Adapters.Postgres.Checks.ForeignKeyNullability (bylaw_postgres v0.1.0-alpha.1)

Copy Markdown View Source

Validates that Postgres foreign key columns are not nullable.

Examples

Before, the foreign key allows missing parents:

CREATE TABLE orders (
  id uuid PRIMARY KEY,
  account_id uuid REFERENCES accounts(id)
);

That makes the association optional even if the application treats every order as belonging to an account. Code then has to handle impossible NULL cases.

After, make the required relationship non-nullable:

CREATE TABLE orders (
  id uuid PRIMARY KEY,
  account_id uuid NOT NULL REFERENCES accounts(id)
);

The database shape now matches the domain model, and callers can rely on the relationship being present.

Notes

This check only inspects columns that are already part of a foreign key constraint. Optional relationships should be excluded with an except matcher.

Options

By default the check inspects all non-system schemas in a Postgres target. Use rules: [[only: ...]] to narrow the scope or exclude intentionally optional foreign keys:

{Bylaw.Db.Adapters.Postgres.Checks.ForeignKeyNullability,
 rules: [
   [
     only: [schema: "public"],
     except: [
       [table: "runs", column: "assistant_message_id"],
       [constraint: "messages_parent_message_id_fkey"]
     ]
   ]
 ]}

Usage

Add this module to the checks passed to Bylaw.Db.Adapters.Postgres.validate/2. See the README usage section for the full ExUnit setup.

Summary

Functions

Implements the Bylaw.Db.Check validation callback.

Types

check_opt()

@type check_opt() :: {:validate, boolean()} | {:rules, [rule()]}

check_opts()

@type check_opts() :: [check_opt()]

matcher()

@type matcher() :: [
  schema: matcher_values(),
  table: matcher_values(),
  constraint: matcher_values(),
  column: matcher_values()
]

matcher_value()

@type matcher_value() :: String.t() | Regex.t()

matcher_values()

@type matcher_values() :: matcher_value() | [matcher_value()]

rule()

@type rule() :: [only: matcher() | [matcher()], except: matcher() | [matcher()]]

Functions

validate(target, opts)

@spec validate(target :: Bylaw.Db.Target.t(), opts :: check_opts()) ::
  Bylaw.Db.Check.result()

Implements the Bylaw.Db.Check validation callback.