Replicant.Decoder.Wal2json (Replicant v1.4.0)

Copy Markdown View Source

The wal2json decoder — JSON format version 2 (ADR-0009 §4).

One JSON document per action (B, C, I, U, D, T, M; anchors in .kimosabe/intents/pglogical-wal2json-decoders.md). The decoder requests include-transaction, include-lsn, include-xids, include-timestamp, include-types, include-type-oids, include-pk and numeric-data-types-as-string (wal2json ≥ 2.6): numerics arrive as JSON strings so no trailing digit is lost, and type names come from the type OIDs through the same OidDatabase call pgoutput's decoder uses. add-tables carries the configured tables.

wal2json sends no relation message, so the decoder synthesizes a Replicant.Decoder.Messages.Relation from the first change it sees for a table and re-emits it ahead of any change whose column list differs (ADR-0009 §5) — the existing schema-change classification then runs unchanged. A column ABSENT from a change's columns list is wal2json's unchanged-TOAST sentinel (the plugin simply skips it), which this decoder surfaces as the first-class :unchanged_toast marker. The relation's replica_identity and stable id come from the connect-time catalog read in the cache.

Documented divergences from the pgoutput contract

wal2json's format 2 CANNOT express a dropped column: the plugin omits a column only when it is unchanged-TOASTed, so a column that vanishes from the change stream is indistinguishable from an untouched TOASTed column and surfaces as the unchanged sentinel indefinitely — the assembler's destructive-drop classification (Critical Rule 4) never fires under this decoder. A dropped column is therefore caught at the NEXT reconnect's catalog read (the synthesized relation shrinks) rather than in stream. A column ADD is detected and classified as usual (the append-only drift merge above).