Localize.Ecto.Audit (Localize Ecto v0.3.0)

Copy Markdown View Source

Audits the PostgreSQL server's collation and Unicode state against the running application.

Collations are compiled into indexes: when a PostgreSQL upgrade (or an OS upgrade underneath it) links a newer ICU library whose collation data changed, every index built with an affected collation is silently inconsistent with new comparisons until it is reindexed. PostgreSQL records the collation version each collation was created with and warns on first use after a change; this module surfaces the drift proactively and generates the remediation statements.

The primary public API is report/1 — used by the mix localize.ecto.audit task — with collation_drift/1, database_collation_drift/1, remediation_sql/1 and unicode_versions/1 as the individual checks.

All functions take a started Ecto.Repo for a PostgreSQL database.

Summary

Functions

Returns the collations whose recorded version differs from the collation library's current version.

Returns the database default collation's version drift, or nil when there is none.

Returns the remediation statements for one entry of collation_drift/1.

Runs every audit and returns the combined result.

Compares the application's IANA time zone inventory with the server's.

Returns the Unicode-relevant versions of the server and the application.

Functions

collation_drift(repo)

@spec collation_drift(module()) :: [map()]

Returns the collations whose recorded version differs from the collation library's current version.

Arguments

  • repo is a started Ecto.Repo module for a PostgreSQL database.

Returns

  • A list of maps with :name, :stored_version, :actual_version and :indexes (the names of indexes depending on the collation, which need reindexing). An empty list means no drift.

Examples

Localize.Ecto.Audit.collation_drift(MyApp.Repo)
#=> []

database_collation_drift(repo)

@spec database_collation_drift(module()) :: map() | nil

Returns the database default collation's version drift, or nil when there is none.

The database default collation orders every text column without an explicit collation, so drift here potentially affects every index on text columns.

Arguments

  • repo is a started Ecto.Repo module for a PostgreSQL database.

Returns

  • nil when the default collation version matches, or a map with :collation, :stored_version and :actual_version.

remediation_sql(map)

@spec remediation_sql(map()) :: [String.t()]

Returns the remediation statements for one entry of collation_drift/1.

Reindex first, then refresh the recorded version — refreshing first would hide the drift while the indexes are still stale.

Arguments

Returns

  • A list of SQL statements.

Examples

iex> Localize.Ecto.Audit.remediation_sql(%{name: "de-x-icu", indexes: ["idx_names"], stored_version: "153.14", actual_version: "153.120"})
[~s[REINDEX INDEX "idx_names"], ~s[ALTER COLLATION "de-x-icu" REFRESH VERSION]]

report(repo)

@spec report(module()) :: map()

Runs every audit and returns the combined result.

Arguments

  • repo is a started Ecto.Repo module for a PostgreSQL database.

Returns

  • A map with :collation_drift, :database_collation_drift, :unicode_versions, :timezone_audit and :ok?true when nothing needs attention.

timezone_audit(repo)

@spec timezone_audit(module()) :: map()

Compares the application's IANA time zone inventory with the server's.

A zone name the server does not know fails at query time in AT TIME ZONE; a zone the application does not know cannot be validated by Localize.Ecto.Type.TimeZone. Small differences are normal — the server's tzdata and CLDR's zone inventory update on different schedules — but zones the application writes must exist on the server.

Arguments

  • repo is a started Ecto.Repo module for a PostgreSQL database.

Returns

  • A map with :unknown_to_server (canonical CLDR zones missing from pg_timezone_names) and :unknown_to_application (server zones absent from the CLDR inventory, excluding the posix/, Etc/ and abbreviation-style entries PostgreSQL adds).

unicode_versions(repo)

@spec unicode_versions(module()) :: map()

Returns the Unicode-relevant versions of the server and the application.

Arguments

  • repo is a started Ecto.Repo module for a PostgreSQL database.

Returns

  • A map with :server (:postgres, :unicode, :icu_unicode — the latter two nil before PostgreSQL 17) and :application (:cldr, :unicode). When the server's ICU Unicode version and the application's CLDR-implied Unicode version differ, :drift? is true — collation results computed in Elixir by Localize.Collation may then order edge-case strings differently from the server.