# `Bylaw.Db.Adapters.Postgres.Checks.ForeignKeyNullability`
[🔗](https://github.com/ryanzidago/bylaw/blob/v0.1.0-alpha.1/lib/bylaw/db/adapters/postgres/checks/foreign_key_nullability.ex#L1)

Validates that Postgres foreign key columns are not nullable.

## Examples

Before, the foreign key allows missing parents:

```sql
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:

```sql
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:

```elixir
{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](readme.html#usage) for the full ExUnit setup.

# `check_opt`

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

# `check_opts`

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

# `matcher`

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

# `matcher_value`

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

# `matcher_values`

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

# `rule`

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

# `validate`

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

Implements the `Bylaw.Db.Check` validation callback.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
