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

Copy Markdown View Source

Validates that Postgres columns do not use configured forbidden types.

Examples

With types: [[type: "json", prefer: "jsonb"]], before:

CREATE TABLE webhook_events (
  id uuid PRIMARY KEY,
  payload json NOT NULL
);

The project has decided this type is limiting or unsafe for its use case. For example, plain json is less useful for common indexing and containment queries than jsonb.

After, use the preferred type:

CREATE TABLE webhook_events (
  id uuid PRIMARY KEY,
  payload jsonb NOT NULL
);

The column now follows the project convention and avoids repeating the same migration decision in future tables.

Notes

This check is policy-driven and has no built-in opinion about which types are bad. Type matchers compare against pg_catalog.format_type, so use exact strings such as "json" or regexes such as ~r/^character\(/.

Options

By default the check inspects all non-system schemas in a Postgres target. Use rules: [...] to configure forbidden types for scoped groups of columns:

{Bylaw.Db.Adapters.Postgres.Checks.ForbiddenColumnTypes,
 rules: [
   [
     only: [schema: "public"],
     types: [
       [type: "json", prefer: "jsonb", reason: "jsonb supports common indexing patterns"],
       [type: ~r/^character\(/, prefer: "text"]
     ],
     except: [[table: "webhook_events", column: "raw_payload"]]
   ]
 ]}

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, [scope_rule()]}

check_opts()

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

matcher()

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

matcher_value()

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

matcher_values()

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

normalized_rule()

@type normalized_rule() :: %{
  type: type_matcher(),
  prefer: String.t() | nil,
  reason: String.t() | nil
}

scope_rule()

@type scope_rule() :: [
  only: matcher() | [matcher()],
  except: matcher() | [matcher()],
  types: [type_rule()]
]

type_matcher()

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

type_rule()

@type type_rule() ::
  type_matcher()
  | [type: type_matcher(), prefer: String.t(), reason: String.t()]

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.