Threadline.Capture.TriggerSQL (Threadline v0.4.0)

Copy Markdown View Source

Generates PL/pgSQL trigger DDL for Threadline audit capture.

The trigger function uses txid_current() to group row changes from the same database transaction under a single audit_transactions row. This approach is transaction-pooling safe per D-06: no session-local configuration writes. Optional audit_transactions.actor_ref is read from the transaction-local GUC threadline.actor_ref (published by the host application in the same transaction — see D-09); the trigger only reads this setting and never assigns session configuration from PL/pgSQL. The txid column on audit_transactions has a UNIQUE constraint so concurrent INSERTs with ON CONFLICT DO NOTHING are safe.

Before-values (changed_from)

The default threadline_capture_changes() always writes changed_from as SQL NULL. To capture sparse prior-row JSON on UPDATE for specific tables, generate a migration with mix threadline.gen.triggers --tables ... --store-changed-from (and optional --except-columns col1,col2). That emits a per-table function threadline_capture_changes_<table>() and rewires triggers to call it.

Redaction (:exclude / :mask)

When non-empty column lists are passed to install_function/1 or install_function_for_table/2, keys are removed (:exclude) or replaced with a stable placeholder (:mask) in data_after (and in changed_from when enabled). except_columns (per-table only) still removes keys from changed_fields / changed_from only; exclude also strips keys from the full-row data_after JSON. Union of both applies to change detection.

json / jsonb columns: masking replaces the entire column value with the placeholder (no deep redaction).

Summary

Functions

Returns SQL to install a trigger on the given table.

Returns SQL to drop the global trigger function.

Returns SQL to drop a per-table capture function (use after dropping triggers, or with CASCADE).

Returns SQL to drop a trigger from the given table.

Returns SQL to create or replace the threadline_capture_changes() trigger function.

Returns SQL to create or replace threadline_capture_changes_<table>() with UPDATE-time sparse changed_from built from OLD for keys in changed_fields (after except_columns and exclude are removed). Requires store_changed_from: true or non-empty :exclude / :mask.

Functions

create_trigger(table_name, mode \\ :default)

Returns SQL to install a trigger on the given table.

  • :default — calls threadline_capture_changes() (default).
  • :per_table — calls threadline_capture_changes_<table>() from install_function_for_table/2.

drop_function()

Returns SQL to drop the global trigger function.

drop_function_for_table(table_name)

Returns SQL to drop a per-table capture function (use after dropping triggers, or with CASCADE).

drop_trigger(table_name)

Returns SQL to drop a trigger from the given table.

install_function()

Returns SQL to create or replace the threadline_capture_changes() trigger function.

The function assumes audit_transactions and audit_changes tables are accessible via the current search_path. changed_from is always written as NULL (use install_function_for_table/2 for opt-in prior values).

Options

  • :exclude — column names omitted entirely from data_after and from changed_fields.
  • :mask — column names whose values become the placeholder in data_after (after excludes).
  • :mask_placeholder — optional string; validated via RedactionPolicy (default "[REDACTED]").

When both lists are empty, SQL is identical to the historical global function.

install_function(opts)

install_function_for_table(table_name, opts)

Returns SQL to create or replace threadline_capture_changes_<table>() with UPDATE-time sparse changed_from built from OLD for keys in changed_fields (after except_columns and exclude are removed). Requires store_changed_from: true or non-empty :exclude / :mask.

Options

  • :store_changed_from — when true, populate changed_from on UPDATE.
  • :except_columns — omit from changed_fields / changed_from (does not strip from data_after).
  • :exclude, :mask, :mask_placeholder — same semantics as install_function/1 for row JSON.