equivalent of <command>SELECT FOR UPDATE</command>. An FDW can detect whether
a table is an <command>UPDATE</command>/<command>DELETE</command> target at plan time
by comparing its relid to <literal>root->parse->resultRelation</literal>,
or at execution time by using <function>ExecRelationIsTargetRelation()</function>.
An alternative possibility is to perform late locking within the
<function>ExecForeignUpdate</function> or <function>ExecForeignDelete</function>
callback, but no special support is provided for this.
</para>
<para>
For foreign tables that are specified to be locked by a <command>SELECT
FOR UPDATE/SHARE</command> command, the <literal>ForeignScan</literal> operation can
again perform early locking by fetching tuples with the equivalent
of <command>SELECT FOR UPDATE/SHARE</command>. To perform late locking
instead, provide the callback functions defined
in <xref linkend="fdw-callbacks-row-locking"/>.
In <function>GetForeignRowMarkType</function>, select rowmark option
<literal>ROW_MARK_EXCLUSIVE</literal>, <literal>ROW_MARK_NOKEYEXCLUSIVE</literal>,
<literal>ROW_MARK_SHARE</literal>, or <literal>ROW_MARK_KEYSHARE</literal> depending
on the requested lock strength. (The core code will act the same
regardless of which of these four options you choose.)
Elsewhere, you can detect whether a foreign table was specified to be
locked by this type of command by using <function>get_plan_rowmark</function> at
plan time, or <function>ExecFindRowMark</function> at execution time; you must
check not only whether a non-null rowmark struct is returned, but that
its <structfield>strength</structfield> field is not <literal>LCS_NONE</literal>.
</para>
<para>
Lastly, for foreign tables that are used in an <command>UPDATE</command>,
<command>DELETE</command> or <command>SELECT FOR UPDATE/SHARE</command> command but
are not specified to be row-locked, you can override the default choice
to copy entire rows by having <function>GetForeignRowMarkType</function> select
option <literal>ROW_MARK_REFERENCE</literal> when it sees lock strength
<literal>LCS_NONE</literal>. This will cause <function>RefetchForeignRow</function> to
be called with that value for <structfield>markType</structfield>; it should then
re-fetch the row without acquiring any new lock. (If you have
a <function>GetForeignRowMarkType</function> function but don't wish to re-fetch
unlocked rows, select option <literal>ROW_MARK_COPY</literal>
for <literal>LCS_NONE</literal>.)
</para>
<para>
See <filename>src/include/nodes/lockoptions.h</filename>, the comments
for <type>RowMarkType</type> and <type>PlanRowMark</type>
in <filename>src/include/nodes/plannodes.h</filename>, and the comments for
<type>ExecRowMark</type> in <filename>src/include/nodes/execnodes.h</filename> for
additional information.
</para>
</sect1>
</chapter>