the foreign table is
the partition chosen for tuple routing or the target specified in the
command.
</para>
<para>
If the <function>BeginForeignInsert</function> pointer is set to
<literal>NULL</literal>, no action is taken for the initialization.
</para>
<para>
Note that if the FDW does not support routable foreign-table partitions
and/or executing <command>COPY FROM</command> on foreign tables, this
function or <function>ExecForeignInsert/ExecForeignBatchInsert</function>
subsequently called must throw error as needed.
</para>
<para>
<programlisting>
void
EndForeignInsert(EState *estate,
ResultRelInfo *rinfo);
</programlisting>
End the insert operation and release resources. It is normally not important
to release palloc'd memory, but for example open files and connections
to remote servers should be cleaned up.
</para>
<para>
If the <function>EndForeignInsert</function> pointer is set to
<literal>NULL</literal>, no action is taken for the termination.
</para>
<para>
<programlisting>
int
IsForeignRelUpdatable(Relation rel);
</programlisting>
Report which update operations the specified foreign table supports.
The return value should be a bit mask of rule event numbers indicating
which operations are supported by the foreign table, using the
<literal>CmdType</literal> enumeration; that is,
<literal>(1 << CMD_UPDATE) = 4</literal> for <command>UPDATE</command>,
<literal>(1 << CMD_INSERT) = 8</literal> for <command>INSERT</command>, and
<literal>(1 << CMD_DELETE) = 16</literal> for <command>DELETE</command>.
</para>
<para>
If the <function>IsForeignRelUpdatable</function> pointer is set to
<literal>NULL</literal>, foreign tables are assumed to be insertable, updatable,
or deletable if the FDW provides <function>ExecForeignInsert</function>,
<function>ExecForeignUpdate</function>, or <function>ExecForeignDelete</function>
respectively. This function is only needed if the FDW supports some
tables that are updatable and some that are not. (Even then, it's
permissible to throw an error in the execution routine instead of
checking in this function. However, this function is used to determine
updatability for display in the <literal>information_schema</literal> views.)
</para>
<para>
Some inserts, updates, and deletes to foreign tables can be optimized
by implementing an alternative set of interfaces. The ordinary
interfaces for inserts, updates, and deletes fetch rows from the remote
server and then modify those rows one at a time. In some cases, this
row-by-row approach is necessary, but it can be inefficient. If it is
possible for the foreign server to determine which rows should be
modified without actually retrieving them, and if there are no local
structures which would affect the operation (row-level local triggers,
stored generated columns, or <literal>WITH CHECK OPTION</literal>
constraints from parent views), then it is possible to arrange things
so that the entire operation is performed on the remote server. The
interfaces described below make this possible.
</para>
<para>
<programlisting>
bool
PlanDirectModify(PlannerInfo *root,
ModifyTable *plan,
Index resultRelation,
int subplan_index);
</programlisting>
Decide whether it is safe to execute a direct modification
on the remote server. If so, return <literal>true</literal> after performing
planning actions needed for that. Otherwise, return <literal>false</literal>.
This optional function is called during query planning.
If this function succeeds, <function>BeginDirectModify</function>,
<function>IterateDirectModify</function> and <function>EndDirectModify</function> will