{"kind": "decode", "major": "18", "item": {"slug": "test_decoding", "name": "test_decoding", "name_zh": "Testing and examples", "category": "Testing and examples", "summary": "A test and example output plugin that renders logical changes in a textual format.", "aliases": [], "content_hash": "a1b90f20b336448cd0dab98bbbc209fb456cb9f0e72d650ae2b75691f17ee413", "versions": {"10": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "7"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "No handler registered in this build", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "Not registered"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/10/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 10.23 source archive", "label": "10.23", "major": "10", "channel": "historical", "revision": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "source_url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/10/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 10 English manual", "sha256": "8463836c180cf30bf33dff157110defa581019d9da4064a80d6571b4e97ce8ce"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 81, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:81", "sha256": "337c1ad2052f53684ee0bba7e6e1f31312caa1f26a27c641b6d69ff157329bba", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "/docs/10/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 10 English manual", "sha256": "c023fc2750375bbd45d810f49639e224a847e4ee32db70bdc154b26c397498bc"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "filter_by_origin_cb": "pg_decode_filter"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.41.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre></div>", "manual_path": "/docs/10/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "filter_by_origin_cb": "pg_decode_filter"}, "source_options": ["force-binary", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts"], "protocol_versions": {}}, "comparison_hash": "bcccdd6dcf62a1e1dc0e1e7c1ae3ad087f88d5bd0e2940ce85a291271f7a9a16", "runtime_verified": false}, "11": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "8"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/11/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 11.22 source archive", "label": "11.22", "major": "11", "channel": "historical", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "source_url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/11/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 11 English manual", "sha256": "9eec639bc68c06e84b15a821ea3c81238313936af94eda0b43abadb68fcff541"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 75, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:75", "sha256": "88cd177db67c0eea08efe94aeaded0c678f4f474d34156558acc43f61e98305d", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "/docs/11/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 11 English manual", "sha256": "69b72c5a11a8905c173c8db4a5322f1d58e7876cbc706c7f4feb99402b6ab274"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.40.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n</div>", "manual_path": "/docs/11/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts"], "protocol_versions": {}}, "comparison_hash": "738ac0f40cbeb95cf50bf83c7406775489147586500a397873551a69cd860c02", "runtime_verified": false}, "12": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "8"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/12/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 12.22 source archive", "label": "12.22", "major": "12", "channel": "historical", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "source_url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/12/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 12 English manual", "sha256": "8a5251bb67bc93fbb96494c450291dd5e68c288ed6dff442001ba8bb2539d739"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 75, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:75", "sha256": "52a8899e51065f8ef839720d7d675b79fb8a9a047bce1cd68aa037d0eaaf5f88", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "/docs/12/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 12 English manual", "sha256": "996af632b11f48ee4f102c7b63c8bf6a2f0e2b6debc1bc76d34a27775c0556b1"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.40.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n</div>", "manual_path": "/docs/12/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts"], "protocol_versions": {}}, "comparison_hash": "738ac0f40cbeb95cf50bf83c7406775489147586500a397873551a69cd860c02", "runtime_verified": false}, "13": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "8"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/13/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 13.23 source archive", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/13/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 13 English manual", "sha256": "7c38cbe2595dbfd0a4064b94569bfb1d75b43adc1d59d7e86367966f22fd0f3b"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 75, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:75", "sha256": "621b7b48baa72c1e3f328108ebfeba6a64338df64e1eb5c2a72d3e41b0c0b3fb", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "/docs/13/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 13 English manual", "sha256": "a9a536d274ad7fb994ae70df068b06da58b5077aca4ce86289ed07921baefd4f"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.40.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n</div>", "manual_path": "/docs/13/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "filter_by_origin_cb": "pg_decode_filter"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts"], "protocol_versions": {}}, "comparison_hash": "738ac0f40cbeb95cf50bf83c7406775489147586500a397873551a69cd860c02", "runtime_verified": false}, "14": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/14/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 14.24 source archive", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/14/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 14 English manual", "sha256": "585d75e17fe03157d1563f3ce13110b6a6768ff0db1b836e0fc490b59fcaa75d"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 133, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:133", "sha256": "4df3c026a3c1f82ac0e98cb4f1564e7fd81f33b6c22b81cdf42babb9bed322f0", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "/docs/14/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 14 English manual", "sha256": "8657a205ee5dc4698b76016d8df9f89a0aea844bdeaa5466b2308401ad6b6dc4"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.42.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data                       \n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/14/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "15": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/15/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 15.19 source archive", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/15/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 15 English manual", "sha256": "07650e2734f3133b733d634e59776611445c52edbddd58e6a4c89a69b7750587"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 133, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:133", "sha256": "61e388a9e86a9443ffdf5c007299ef43a51df1c16ef95c72113e118221e7a85d", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "/docs/15/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 15 English manual", "sha256": "6c81b3b643e0a8f47dc1a136953fb61d57b48434a3c8aa7393b06dae440406a5"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.45.\u00a0test_decoding</h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/15/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "16": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/16/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 16.15 source archive", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/16/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 16 English manual", "sha256": "5fe87919271068465a6dda1585f5c4b029c1b93f91d2d27d3130a53fb50ecd55"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 129, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:129", "sha256": "3635be9b98bdb50351c64e77f685110e78f5c02f9f8ca87815d9795ad871badd", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "/docs/16/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 16 English manual", "sha256": "c093330981ad988f2081ad6ac1eb74b0c8ab7fbc19928ca50e12fcdfe7647a4f"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.45.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/16/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "17": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/17/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 17.11 source archive", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/17/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 17 English manual", "sha256": "f7efc73343523984dedbc7bb8a71e3d3c110fc90f5f6340893757c65ceeb27d3"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 129, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:129", "sha256": "35b7df261959d783ac7d1bbaea15044aa55da32b3b3b1c7f259dbc21ece73296", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "/docs/17/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 17 English manual", "sha256": "2be04efbf0e2c4266665b8e7b8ebbc04a92456d3fcfdfe2667e8e4486bd70be8"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.43.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/17/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "18": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/18/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/18/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 18 English manual", "sha256": "630f953dd8c232a410627e4993be253b13665bb1b04ca1be26c871afd7c3eebe"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 132, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:132", "sha256": "3110af5e2b768a3311f20a32ac9d90c7a18f437e0ceaef69fbee51cc28900357", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "/docs/18/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 18 English manual", "sha256": "e5b3d13adfcc9e33f24524cb09d93eb91a1292fdb3124234002ccccf93f45738"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.45.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/18/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "19": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/19/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 19beta4 source archive", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/19/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 19 English manual", "sha256": "bb8605063120a337d288fbdb033cdab716d51547e117a5bbc0ee48a24c057d1f"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 132, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:132", "sha256": "71ab00d5b820393edf509b78cae7b01df29b8318aaefa2cf234c82f43c78463a", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "/docs/19/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 19 English manual", "sha256": "5bbd383a295ed5cdb65b99d721fb7320aafdb7a343b26abbcb022134635d5ff7"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.47.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n    lsn     | xid |                       data\n------------+-----+--------------------------------------------------\n 0/016D30F8 | 691 | BEGIN\n 0/016D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/016D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/016D32A0 | 691 | COMMIT\n 0/016D32D8 | 692 | BEGIN\n 0/016D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/016D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/016D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn     | xid |                       data\n------------+-----+--------------------------------------------------\n 0/016B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/016B21F8 | 503 | streaming change for TXN 503\n 0/016B2300 | 503 | streaming change for TXN 503\n 0/016B2408 | 503 | streaming change for TXN 503\n 0/016BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/016B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/016BECA8 | 503 | streaming change for TXN 503\n 0/016BEDB0 | 503 | streaming change for TXN 503\n 0/016BEEB8 | 503 | streaming change for TXN 503\n 0/016BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/19/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "20": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/devel/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 20devel source archive", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "/docs/devel/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 20 English manual", "sha256": "68eb7c306b53fc205d131101f1e3f2eb622274594d3d479361eda57954eae938"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 132, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:132", "sha256": "cd1c86b7040eee0a4f67eef397295759bba0d920bc70d38b16574f1e47a48086", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "/docs/devel/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 20 English manual", "sha256": "c3155ae81ecabd273f3b326b0e44b4cf39954def59a10c58f50f7ec51ac1923c"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.47.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n    lsn     | xid |                       data\n------------+-----+--------------------------------------------------\n 0/016D30F8 | 691 | BEGIN\n 0/016D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/016D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/016D32A0 | 691 | COMMIT\n 0/016D32D8 | 692 | BEGIN\n 0/016D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/016D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/016D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn     | xid |                       data\n------------+-----+--------------------------------------------------\n 0/016B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/016B21F8 | 503 | streaming change for TXN 503\n 0/016B2300 | 503 | streaming change for TXN 503\n 0/016B2408 | 503 | streaming change for TXN 503\n 0/016BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/016B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/016BECA8 | 503 | streaming change for TXN 503\n 0/016BEDB0 | 503 | streaming change for TXN 503\n 0/016BEEB8 | 503 | streaming change for TXN 503\n 0/016BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/devel/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}}}, "snapshot": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "21"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pg_decode_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pg_decode_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pg_decode_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pg_decode_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pg_decode_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pg_decode_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pg_decode_stream_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pg_decode_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pg_decode_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pg_decode_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "source-options", "rows": [{"name": "force-binary"}, {"name": "include-rewrites"}, {"name": "include-timestamp"}, {"name": "include-xids"}, {"name": "only-local"}, {"name": "skip-empty-xacts"}, {"name": "stream-changes"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/18/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/test_decoding/", "label": "Existing extension catalogue identity"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/18/test-decoding.html", "path": "test-decoding.html", "label": "PostgreSQL 18 English manual", "sha256": "630f953dd8c232a410627e4993be253b13665bb1b04ca1be26c871afd7c3eebe"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 132, "path": "contrib/test_decoding/test_decoding.c", "label": "contrib/test_decoding/test_decoding.c:132", "sha256": "3110af5e2b768a3311f20a32ac9d90c7a18f437e0ceaef69fbee51cc28900357", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "/docs/18/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 18 English manual", "sha256": "e5b3d13adfcc9e33f24524cb09d93eb91a1292fdb3124234002ccccf93f45738"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pg_decode_startup;\n\tcb->begin_cb = pg_decode_begin_txn;\n\tcb->change_cb = pg_decode_change;\n\tcb->truncate_cb = pg_decode_truncate;\n\tcb->commit_cb = pg_decode_commit_txn;\n\tcb->filter_by_origin_cb = pg_decode_filter;\n\tcb->shutdown_cb = pg_decode_shutdown;\n\tcb->message_cb = pg_decode_message;\n\tcb->filter_prepare_cb = pg_decode_filter_prepare;\n\tcb->begin_prepare_cb = pg_decode_begin_prepare_txn;\n\tcb->prepare_cb = pg_decode_prepare_txn;\n\tcb->commit_prepared_cb = pg_decode_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pg_decode_rollback_prepared_txn;\n\tcb->stream_start_cb = pg_decode_stream_start;\n\tcb->stream_stop_cb = pg_decode_stream_stop;\n\tcb->stream_abort_cb = pg_decode_stream_abort;\n\tcb->stream_prepare_cb = pg_decode_stream_prepare;\n\tcb->stream_commit_cb = pg_decode_stream_commit;\n\tcb->stream_change_cb = pg_decode_stream_change;\n\tcb->stream_message_cb = pg_decode_stream_message;\n\tcb->stream_truncate_cb = pg_decode_stream_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "description": ["A test and example output plugin that renders logical changes in a textual format."], "manual_html": "<div class=\"sect1\" id=\"TEST-DECODING\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">F.45.\u00a0test_decoding \u2014 SQL-based test/example module for WAL logical decoding </h2>\n</div>\n</div>\n</div>\n<p><code class=\"filename\">test_decoding</code> is an example of a logical decoding output plugin. It doesn't do anything especially useful, but can serve as a starting point for developing your own output plugin.</p>\n<p><code class=\"filename\">test_decoding</code> receives WAL through the logical decoding mechanism and decodes it into text representations of the operations performed.</p>\n<p>Typical output from this plugin, used over the SQL logical decoding interface, might be:</p>\n<pre class=\"programlisting\">postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');\n   lsn     | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16D30F8 | 691 | BEGIN\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'\n 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'\n 0/16D32A0 | 691 | COMMIT\n 0/16D32D8 | 692 | BEGIN\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2\n 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3\n 0/16D3398 | 692 | COMMIT\n(8 rows)\n</pre>\n<p>We can also get the changes of the in-progress transaction, and the typical output might be:</p>\n<pre class=\"programlisting\">postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');\n    lsn    | xid |                       data\n-----------+-----+--------------------------------------------------\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | streaming change for TXN 503\n 0/16B2300 | 503 | streaming change for TXN 503\n 0/16B2408 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503\n 0/16BECA8 | 503 | streaming change for TXN 503\n 0/16BEDB0 | 503 | streaming change for TXN 503\n 0/16BEEB8 | 503 | streaming change for TXN 503\n 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503\n(10 rows)\n</pre>\n</div>", "manual_path": "/docs/18/test-decoding.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [], "callbacks": {"begin_cb": "pg_decode_begin_txn", "change_cb": "pg_decode_change", "commit_cb": "pg_decode_commit_txn", "message_cb": "pg_decode_message", "prepare_cb": "pg_decode_prepare_txn", "startup_cb": "pg_decode_startup", "shutdown_cb": "pg_decode_shutdown", "truncate_cb": "pg_decode_truncate", "stream_stop_cb": "pg_decode_stream_stop", "stream_abort_cb": "pg_decode_stream_abort", "stream_start_cb": "pg_decode_stream_start", "begin_prepare_cb": "pg_decode_begin_prepare_txn", "stream_change_cb": "pg_decode_stream_change", "stream_commit_cb": "pg_decode_stream_commit", "filter_prepare_cb": "pg_decode_filter_prepare", "stream_message_cb": "pg_decode_stream_message", "stream_prepare_cb": "pg_decode_stream_prepare", "commit_prepared_cb": "pg_decode_commit_prepared_txn", "stream_truncate_cb": "pg_decode_stream_truncate", "filter_by_origin_cb": "pg_decode_filter", "rollback_prepared_cb": "pg_decode_rollback_prepared_txn"}, "source_options": ["force-binary", "include-rewrites", "include-timestamp", "include-xids", "only-local", "skip-empty-xacts", "stream-changes"], "protocol_versions": {}}, "comparison_hash": "465d2c6d5759db47dd963a4b8f5bcb847943413cfd5afb7eb4fd0bd7b894b83e", "runtime_verified": false}, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}