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).