last_write)</function> has to be
called to perform the write. The <parameter>last_write</parameter>
indicates whether a particular write was the callback's last write.
</para>
<para>
The following example shows how to output data to the consumer of an
output plugin:
<programlisting>
OutputPluginPrepareWrite(ctx, true);
appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
OutputPluginWrite(ctx, true);
</programlisting>
</para>
</sect2>
</sect1>
<sect1 id="logicaldecoding-writer">
<title>Logical Decoding Output Writers</title>
<para>
It is possible to add more output methods for logical decoding.
For details, see
<filename>src/backend/replication/logical/logicalfuncs.c</filename>.
Essentially, three functions need to be provided: one to read WAL, one to
prepare writing output, and one to write the output
(see <xref linkend="logicaldecoding-output-plugin-output"/>).
</para>
</sect1>
<sect1 id="logicaldecoding-synchronous">
<title>Synchronous Replication Support for Logical Decoding</title>
<sect2 id="logicaldecoding-synchronous-overview">
<title>Overview</title>
<para>
Logical decoding can be used to build
<link linkend="synchronous-replication">synchronous
replication</link> solutions with the same user interface as synchronous
replication for <link linkend="streaming-replication">streaming
replication</link>. To do this, the streaming replication interface
(see <xref linkend="logicaldecoding-walsender"/>) must be used to stream out
data. Clients have to send <literal>Standby status update (F)</literal>
(see <xref linkend="protocol-replication"/>) messages, just like streaming
replication clients do.
</para>
<note>
<para>
A synchronous replica receiving changes via logical decoding will work in
the scope of a single database. Since, in contrast to
that, <parameter>synchronous_standby_names</parameter> currently is
server wide, this means this technique will not work properly if more
than one database is actively used.
</para>
</note>
</sect2>
<sect2 id="logicaldecoding-synchronous-caveats">
<title>Caveats</title>
<para>
In synchronous replication setup, a deadlock can happen, if the transaction
has locked [user] catalog tables exclusively. See
<xref linkend="logicaldecoding-capabilities"/> for information on user
catalog tables. This is because logical decoding of transactions can lock
catalog tables to access them. To avoid this users must refrain from taking
an exclusive lock on [user] catalog tables. This can happen in the following
ways:
<itemizedlist>
<listitem>
<para>
Issuing an explicit <command>LOCK</command> on <structname>pg_class</structname>
in a transaction.
</para>
</listitem>
<listitem>
<para>
Perform <command>CLUSTER</command> on <structname>pg_class</structname> in
a transaction.
</para>
</listitem>
<listitem>
<para>
<command>PREPARE TRANSACTION</command> after <command>LOCK</command> command
on <structname>pg_class</structname> and allow logical decoding of two-phase
transactions.
</para>
</listitem>
<listitem>
<para>
<command>PREPARE TRANSACTION</command> after <command>CLUSTER</command>
command on <structname>pg_trigger</structname> and allow logical decoding of
two-phase transactions. This will lead to deadlock only when published table
have a trigger.
</para>
</listitem>
<listitem>
<para>
Executing <command>TRUNCATE</command> on [user] catalog table in a
transaction.
</para>
</listitem>
</itemizedlist>
Note that these commands can cause deadlocks not only for the system
catalog tables listed above but for other catalog