void
 deparseTruncateSql(StringInfo buf,
                   List *rels,
-                  List *rels_extra,
                   DropBehavior behavior,
                   bool restart_seqs)
 {
-   ListCell   *lc1,
-              *lc2;
+   ListCell   *cell;
 
    appendStringInfoString(buf, "TRUNCATE ");
 
-   forboth(lc1, rels, lc2, rels_extra)
+   foreach(cell, rels)
    {
-       Relation    rel = lfirst(lc1);
-       int         extra = lfirst_int(lc2);
+       Relation    rel = lfirst(cell);
 
-       if (lc1 != list_head(rels))
+       if (cell != list_head(rels))
            appendStringInfoString(buf, ", ");
-       if (extra & TRUNCATE_REL_CONTEXT_ONLY)
-           appendStringInfoString(buf, "ONLY ");
 
        deparseRelation(buf, rel);
    }
 
 -- test for TRUNCATE
 -- ===================================================================
 CREATE TABLE tru_rtable0 (id int primary key);
-CREATE TABLE tru_rtable1 (id int primary key);
 CREATE FOREIGN TABLE tru_ftable (id int)
        SERVER loopback OPTIONS (table_name 'tru_rtable0');
 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
 CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
 CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
                             FOR VALUES WITH (MODULUS 2, REMAINDER 0);
+CREATE TABLE tru_rtable1 (id int primary key);
 CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
                                     FOR VALUES WITH (MODULUS 2, REMAINDER 1)
        SERVER loopback OPTIONS (table_name 'tru_rtable1');
 (1 row)
 
 -- truncate with ONLY clause
+-- Since ONLY is specified, the table tru_ftable_child that inherits
+-- tru_ftable_parent locally is not truncated.
 TRUNCATE ONLY tru_ftable_parent;
 SELECT sum(id) FROM tru_ftable_parent;  -- 126
  sum 
   95
 (1 row)
 
-TRUNCATE ONLY tru_ftable;      -- truncate only parent portion
-SELECT sum(id) FROM tru_ftable;   -- 60
- sum 
------
-  60
+-- Both parent and child tables in the foreign server are truncated
+-- even though ONLY is specified because ONLY has no effect
+-- when truncating a foreign table.
+TRUNCATE ONLY tru_ftable;
+SELECT count(*) FROM tru_ftable;   -- 0
+ count 
+-------
+     0
 (1 row)
 
 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
-SELECT sum(id) FROM tru_ftable;        -- 175
+INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
+SELECT sum(id) FROM tru_ftable;        -- 255
  sum 
 -----
- 175
+ 255
 (1 row)
 
 TRUNCATE tru_ftable;           -- truncate both of parent and child
-SELECT count(*) FROM tru_ftable;    -- empty
+SELECT count(*) FROM tru_ftable;    -- 0
  count 
 -------
      0
 
 static void postgresExplainDirectModify(ForeignScanState *node,
                                        ExplainState *es);
 static void postgresExecForeignTruncate(List *rels,
-                                       List *rels_extra,
                                        DropBehavior behavior,
                                        bool restart_seqs);
 static bool postgresAnalyzeForeignTable(Relation relation,
  */
 static void
 postgresExecForeignTruncate(List *rels,
-                           List *rels_extra,
                            DropBehavior behavior,
                            bool restart_seqs)
 {
 
    /* Construct the TRUNCATE command string */
    initStringInfo(&sql);
-   deparseTruncateSql(&sql, rels, rels_extra, behavior, restart_seqs);
+   deparseTruncateSql(&sql, rels, behavior, restart_seqs);
 
    /* Issue the TRUNCATE command to remote server */
    do_sql_command(conn, sql.data);
 
                              List **retrieved_attrs);
 extern void deparseTruncateSql(StringInfo buf,
                               List *rels,
-                              List *rels_extra,
                               DropBehavior behavior,
                               bool restart_seqs);
 extern void deparseStringLiteral(StringInfo buf, const char *val);
 
 -- test for TRUNCATE
 -- ===================================================================
 CREATE TABLE tru_rtable0 (id int primary key);
-CREATE TABLE tru_rtable1 (id int primary key);
 CREATE FOREIGN TABLE tru_ftable (id int)
        SERVER loopback OPTIONS (table_name 'tru_rtable0');
 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
 CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
 CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
                             FOR VALUES WITH (MODULUS 2, REMAINDER 0);
+CREATE TABLE tru_rtable1 (id int primary key);
 CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
                                     FOR VALUES WITH (MODULUS 2, REMAINDER 1)
        SERVER loopback OPTIONS (table_name 'tru_rtable1');
 SELECT count(*) from tru_pk_ftable; -- 0
 
 -- truncate with ONLY clause
+-- Since ONLY is specified, the table tru_ftable_child that inherits
+-- tru_ftable_parent locally is not truncated.
 TRUNCATE ONLY tru_ftable_parent;
 SELECT sum(id) FROM tru_ftable_parent;  -- 126
 TRUNCATE tru_ftable_parent;
 INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(10,14) x);
 SELECT sum(id) FROM tru_ftable;   -- 95
 
-TRUNCATE ONLY tru_ftable;      -- truncate only parent portion
-SELECT sum(id) FROM tru_ftable;   -- 60
+-- Both parent and child tables in the foreign server are truncated
+-- even though ONLY is specified because ONLY has no effect
+-- when truncating a foreign table.
+TRUNCATE ONLY tru_ftable;
+SELECT count(*) FROM tru_ftable;   -- 0
 
 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
-SELECT sum(id) FROM tru_ftable;        -- 175
+INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
+SELECT sum(id) FROM tru_ftable;        -- 255
 TRUNCATE tru_ftable;           -- truncate both of parent and child
-SELECT count(*) FROM tru_ftable;    -- empty
+SELECT count(*) FROM tru_ftable;    -- 0
 
 -- cleanup
 DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable__p1,tru_ftable;
 
     <para>
 <programlisting>
 void
-ExecForeignTruncate(List *rels, List *rels_extra,
-                    DropBehavior behavior, bool restart_seqs);
+ExecForeignTruncate(List *rels,
+                    DropBehavior behavior,
+                    bool restart_seqs);
 </programlisting>
 
      Truncate a set of foreign tables specified in <literal>rels</literal>.
      This function is called when <xref linkend="sql-truncate"/> is executed
      on foreign tables.  <literal>rels</literal> is the list of
      <structname>Relation</structname> data structure that indicates
-     a foreign table to truncate.  <literal>rels_extra</literal> the list of
-     <literal>int</literal> value, which delivers extra information about
-     a foreign table to truncate.  Possible values are
-     <literal>TRUNCATE_REL_CONTEXT_NORMAL</literal>, which means that
-     the foreign table is specified WITHOUT <literal>ONLY</literal> clause
-     in <command>TRUNCATE</command>,
-     <literal>TRUNCATE_REL_CONTEXT_ONLY</literal>, which means that
-     the foreign table is specified WITH <literal>ONLY</literal> clause,
-     and <literal>TRUNCATE_REL_CONTEXT_CASCADING</literal>,
-     which means that the foreign table is not specified explicitly,
-     but will be truncated due to dependency (for example, partition table).
-     There is one-to-one mapping between <literal>rels</literal> and
-     <literal>rels_extra</literal>.  The number of entries is the same
-     between the two lists.
+     a foreign table to truncate.
     </para>
 
     <para>
      if <literal>CONTINUE IDENTITY</literal> option is specified.
     </para>
 
+    <para>
+     Note that the <literal>ONLY</literal> options specified
+     in the original <command>TRUNCATE</command> command are not passed to
+     <function>ExecForeignTruncate</function>.  This behavior is similar to
+     the callback functions of <command>SELECT</command>,
+     <command>UPDATE</command> and <command>DELETE</command> on
+     a foreign table.
+    </para>
+
     <para>
      <command>TRUNCATE</command> invokes
      <function>ExecForeignTruncate</function> once per foreign server
 
   have privileges to do these things.)
  </para>
 
+ <para>
+  Note that the <literal>ONLY</literal> option specified in
+  <command>SELECT</command>, <command>UPDATE</command>,
+  <command>DELETE</command> or <command>TRUNCATE</command>
+  has no effect when accessing or modifying the remote table.
+ </para>
+
  <para>
   Note that <filename>postgres_fdw</filename> currently lacks support for
   <command>INSERT</command> statements with an <literal>ON CONFLICT DO
 
 {
    Oid         serverid;
    List       *rels;
-   List       *rels_extra;
 } ForeignTruncateInfo;
 
 /*
 {
    List       *rels = NIL;
    List       *relids = NIL;
-   List       *relids_extra = NIL;
    List       *relids_logged = NIL;
    ListCell   *cell;
 
 
        rels = lappend(rels, rel);
        relids = lappend_oid(relids, myrelid);
-       relids_extra = lappend_int(relids_extra, (recurse ?
-                                                 TRUNCATE_REL_CONTEXT_NORMAL :
-                                                 TRUNCATE_REL_CONTEXT_ONLY));
+
        /* Log this relation only if needed for logical decoding */
        if (RelationIsLogicallyLogged(rel))
            relids_logged = lappend_oid(relids_logged, myrelid);
 
                rels = lappend(rels, rel);
                relids = lappend_oid(relids, childrelid);
-               relids_extra = lappend_int(relids_extra,
-                                          TRUNCATE_REL_CONTEXT_CASCADING);
+
                /* Log this relation only if needed for logical decoding */
                if (RelationIsLogicallyLogged(rel))
                    relids_logged = lappend_oid(relids_logged, childrelid);
                     errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
    }
 
-   ExecuteTruncateGuts(rels, relids, relids_extra, relids_logged,
+   ExecuteTruncateGuts(rels, relids, relids_logged,
                        stmt->behavior, stmt->restart_seqs);
 
    /* And close the rels */
  *
  * explicit_rels is the list of Relations to truncate that the command
  * specified.  relids is the list of Oids corresponding to explicit_rels.
- * relids_extra is the list of integer values that deliver extra information
- * about relations in explicit_rels.  relids_logged is the list of Oids
- * (a subset of relids) that require WAL-logging.  This is all a bit redundant,
- * but the existing callers have this information handy in this form.
+ * relids_logged is the list of Oids (a subset of relids) that require
+ * WAL-logging.  This is all a bit redundant, but the existing callers have
+ * this information handy in this form.
  */
 void
 ExecuteTruncateGuts(List *explicit_rels,
                    List *relids,
-                   List *relids_extra,
                    List *relids_logged,
                    DropBehavior behavior, bool restart_seqs)
 {
    ResultRelInfo *resultRelInfo;
    SubTransactionId mySubid;
    ListCell   *cell;
-   ListCell   *lc1,
-           *lc2;
    Oid        *logrelids;
 
    /*
                truncate_check_activity(rel);
                rels = lappend(rels, rel);
                relids = lappend_oid(relids, relid);
-               relids_extra = lappend_int(relids_extra,
-                                          TRUNCATE_REL_CONTEXT_CASCADING);
+
                /* Log this relation only if needed for logical decoding */
                if (RelationIsLogicallyLogged(rel))
                    relids_logged = lappend_oid(relids_logged, relid);
     */
    mySubid = GetCurrentSubTransactionId();
 
-   Assert(list_length(rels) == list_length(relids_extra));
-   forboth(lc1, rels, lc2, relids_extra)
+   foreach(cell, rels)
    {
-       Relation    rel = (Relation) lfirst(lc1);
-       int         extra = lfirst_int(lc2);
+       Relation    rel = (Relation) lfirst(cell);
 
        /*
         * Save OID of partitioned tables for later; nothing else to do for
            {
                ft_info->serverid = serverid;
                ft_info->rels = NIL;
-               ft_info->rels_extra = NIL;
            }
 
            /*
             * foreign table belongs to.
             */
            ft_info->rels = lappend(ft_info->rels, rel);
-           ft_info->rels_extra = lappend_int(ft_info->rels_extra, extra);
            continue;
        }
 
                Assert(routine->ExecForeignTruncate != NULL);
 
                routine->ExecForeignTruncate(ft_info->rels,
-                                            ft_info->rels_extra,
                                             behavior,
                                             restart_seqs);
            }
 
    List       *rels = NIL;
    List       *part_rels = NIL;
    List       *relids = NIL;
-   List       *relids_extra = NIL;
    List       *relids_logged = NIL;
    ListCell   *lc;
 
        remote_rels = lappend(remote_rels, rel);
        rels = lappend(rels, rel->localrel);
        relids = lappend_oid(relids, rel->localreloid);
-       relids_extra = lappend_int(relids_extra, TRUNCATE_REL_CONTEXT_NORMAL);
        if (RelationIsLogicallyLogged(rel->localrel))
            relids_logged = lappend_oid(relids_logged, rel->localreloid);
 
                rels = lappend(rels, childrel);
                part_rels = lappend(part_rels, childrel);
                relids = lappend_oid(relids, childrelid);
-               relids_extra = lappend_int(relids_extra, TRUNCATE_REL_CONTEXT_CASCADING);
                /* Log this relation only if needed for logical decoding */
                if (RelationIsLogicallyLogged(childrel))
                    relids_logged = lappend_oid(relids_logged, childrelid);
     */
    ExecuteTruncateGuts(rels,
                        relids,
-                       relids_extra,
                        relids_logged,
                        DROP_RESTRICT,
                        restart_seqs);
 
 #include "storage/lock.h"
 #include "utils/relcache.h"
 
-/*
- * These values indicate how a relation was specified as the target to
- * truncate in TRUNCATE command.
- */
-#define TRUNCATE_REL_CONTEXT_NORMAL       1 /* specified without ONLY clause */
-#define TRUNCATE_REL_CONTEXT_ONLY         2 /* specified with ONLY clause */
-#define TRUNCATE_REL_CONTEXT_CASCADING     3   /* not specified but truncated
-                                                * due to dependency (e.g.,
-                                                * partition table) */
-
 struct AlterTableUtilityContext;   /* avoid including tcop/utility.h here */
 
 
 extern void ExecuteTruncate(TruncateStmt *stmt);
 extern void ExecuteTruncateGuts(List *explicit_rels,
                                List *relids,
-                               List *relids_extra,
                                List *relids_logged,
                                DropBehavior behavior,
                                bool restart_seqs);
 
                                               Oid serverOid);
 
 typedef void (*ExecForeignTruncate_function) (List *rels,
-                                             List *rels_extra,
                                              DropBehavior behavior,
                                              bool restart_seqs);