Home Explore Blog CI



postgresql

31th chunk of `doc/src/sgml/fdwhandler.sgml`
5b2e37db9d02c60f81fdb8538da125bf4b567131c0df59290000000100000fa2
 <function>GetForeignPlan</function>.  The recommended place to generate
     such paths is in the <function>GetForeignUpperPaths</function>
     callback function, which is called for each upper relation (i.e., each
     post-scan/join processing step), if all the base relations of the query
     come from the same FDW.
    </para>

    <para>
     <function>PlanForeignModify</function> and the other callbacks described in
     <xref linkend="fdw-callbacks-update"/> are designed around the assumption
     that the foreign relation will be scanned in the usual way and then
     individual row updates will be driven by a local <literal>ModifyTable</literal>
     plan node.  This approach is necessary for the general case where an
     update requires reading local tables as well as foreign tables.
     However, if the operation could be executed entirely by the foreign
     server, the FDW could generate a path representing that and insert it
     into the <literal>UPPERREL_FINAL</literal> upper relation, where it would
     compete against the <literal>ModifyTable</literal> approach.  This approach
     could also be used to implement remote <literal>SELECT FOR UPDATE</literal>,
     rather than using the row locking callbacks described in
     <xref linkend="fdw-callbacks-row-locking"/>.  Keep in mind that a path
     inserted into <literal>UPPERREL_FINAL</literal> is responsible for
     implementing <emphasis>all</emphasis> behavior of the query.
    </para>

    <para>
     When planning an <command>UPDATE</command> or <command>DELETE</command>,
     <function>PlanForeignModify</function> and <function>PlanDirectModify</function>
     can look up the <structname>RelOptInfo</structname>
     struct for the foreign table and make use of the
     <literal>baserel-&gt;fdw_private</literal> data previously created by the
     scan-planning functions.  However, in <command>INSERT</command> the target
     table is not scanned so there is no <structname>RelOptInfo</structname> for it.
     The <structname>List</structname> returned by <function>PlanForeignModify</function> has
     the same restrictions as the <structfield>fdw_private</structfield> list of a
     <structname>ForeignScan</structname> plan node, that is it must contain only
     structures that <function>copyObject</function> knows how to copy.
    </para>

    <para>
     <command>INSERT</command> with an <literal>ON CONFLICT</literal> clause does not
     support specifying the conflict target, as unique constraints or
     exclusion constraints on remote tables are not locally known. This
     in turn implies that <literal>ON CONFLICT DO UPDATE</literal> is not supported,
     since the specification is mandatory there.
    </para>

   </sect1>

   <sect1 id="fdw-row-locking">
    <title>Row Locking in Foreign Data Wrappers</title>

    <para>
     If an FDW's underlying storage mechanism has a concept of locking
     individual rows to prevent concurrent updates of those rows, it is
     usually worthwhile for the FDW to perform row-level locking with as
     close an approximation as practical to the semantics used in
     ordinary <productname>PostgreSQL</productname> tables.  There are multiple
     considerations involved in this.
    </para>

    <para>
     One key decision to be made is whether to perform <firstterm>early
     locking</firstterm> or <firstterm>late locking</firstterm>.  In early locking, a row is
     locked when it is first retrieved from the underlying store, while in
     late locking, the row is locked only when it is known that it needs to
     be locked.  (The difference arises because some rows may be discarded by
     locally-checked restriction or join conditions.)  Early locking is much
     simpler and avoids extra round trips to a remote store, but it can cause
     locking of rows that need not have been locked, resulting in reduced
     concurrency or even unexpected deadlocks.  Also, late locking is only
     possible if the

Title: Foreign Data Wrapper Planning and Row Locking
Summary
This section covers planning modifications on foreign tables, explaining how `PlanForeignModify` uses `RelOptInfo` and handles the special case of INSERT operations. It also details how an FDW can generate a path for an operation that can be entirely executed on the foreign server and insert it into the UPPERREL_FINAL relation, and touches upon the lack of support for specifying conflict targets in INSERT operations with ON CONFLICT clauses. The section then introduces the topic of row locking in FDWs, discussing the key decision between early and late locking and the trade-offs involved.