Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Don't pass "ONLY" options specified in TRUNCATE to foreign data wrapper.
authorFujii Masao <fujii@postgresql.org>
Tue, 27 Apr 2021 05:41:27 +0000 (14:41 +0900)
committerFujii Masao <fujii@postgresql.org>
Tue, 27 Apr 2021 05:41:27 +0000 (14:41 +0900)
Commit 8ff1c94649 allowed TRUNCATE command to truncate foreign tables.
Previously the information about "ONLY" options specified in TRUNCATE
command were passed to the foreign data wrapper. Then postgres_fdw
constructed the TRUNCATE command to issue the remote server and
included "ONLY" options in it based on the passed information.

On the other hand, "ONLY" options specified in SELECT, UPDATE or DELETE
have no effect when accessing or modifying the remote table, i.e.,
are not passed to the foreign data wrapper. So it's inconsistent to
make only TRUNCATE command pass the "ONLY" options to the foreign data
wrapper. Therefore this commit changes the TRUNCATE command so that
it doesn't pass the "ONLY" options to the foreign data wrapper,
for the consistency with other statements. Also this commit changes
postgres_fdw so that it always doesn't include "ONLY" options in
the TRUNCATE command that it constructs.

Author: Fujii Masao
Reviewed-by: Bharath Rupireddy, Kyotaro Horiguchi, Justin Pryzby, Zhihong Yu
Discussion: https://postgr.es/m/551ed8c1-f531-818b-664a-2cecdab99cd8@oss.nttdata.com

contrib/postgres_fdw/deparse.c
contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/postgres_fdw.c
contrib/postgres_fdw/postgres_fdw.h
contrib/postgres_fdw/sql/postgres_fdw.sql
doc/src/sgml/fdwhandler.sgml
doc/src/sgml/postgres-fdw.sgml
src/backend/commands/tablecmds.c
src/backend/replication/logical/worker.c
src/include/commands/tablecmds.h
src/include/foreign/fdwapi.h

index bdc4c3620d0246749cb859f2343a4d6472a1536c..7a798530e3a05cfad2dc9afcc0c4d4a3cda7dd62 100644 (file)
@@ -2179,24 +2179,19 @@ deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
 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);
    }
index 5070d932394906c343024423d1ba7d110fc8905c..8e1cc695081dafdee1a99ddb95fcd2a06d1df428 100644 (file)
@@ -8218,13 +8218,13 @@ drop table loc3;
 -- 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');
@@ -8364,6 +8364,8 @@ SELECT count(*) from tru_pk_ftable; -- 0
 (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 
@@ -8388,22 +8390,26 @@ SELECT sum(id) FROM tru_ftable;   -- 95
   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
index e201b5404e6dc188d2222528cec336d27721611d..8bcdc8d6160dcd4329ee2cc16aafa0fb80e79a3a 100644 (file)
@@ -401,7 +401,6 @@ static void postgresExplainForeignModify(ModifyTableState *mtstate,
 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,
@@ -2881,7 +2880,6 @@ postgresExplainDirectModify(ForeignScanState *node, ExplainState *es)
  */
 static void
 postgresExecForeignTruncate(List *rels,
-                           List *rels_extra,
                            DropBehavior behavior,
                            bool restart_seqs)
 {
@@ -2964,7 +2962,7 @@ postgresExecForeignTruncate(List *rels,
 
    /* 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);
index 5d44b7531409d12d14b2878a20fb3ec96b314a0a..9591c0f6c26d7f9a8f349f6e2fe40ecd89916564 100644 (file)
@@ -209,7 +209,6 @@ extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
                              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);
index 74590089bd19fe6dc2e24df10d40b96ea0585138..dcd36a9753ebd8106e010605f2a937935d7f36d1 100644 (file)
@@ -2355,7 +2355,6 @@ drop table loc3;
 -- 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);
@@ -2363,6 +2362,7 @@ 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');
@@ -2428,6 +2428,8 @@ SELECT count(*) from tru_ftable; -- 0
 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;
@@ -2439,13 +2441,17 @@ INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x);
 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;
index 9f9274ce55fde38fa748e1f58eda6422588c95e2..e08441ec8bce4cf7380d874801f1113b37c42c3f 100644 (file)
@@ -1071,28 +1071,16 @@ EndDirectModify(ForeignScanState *node);
     <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>
@@ -1111,6 +1099,15 @@ ExecForeignTruncate(List *rels, List *rels_extra,
      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
index 5320accf6f4b5b112c1f305eb07845b7a21c9a61..b0806c1274e833ddc838bfdb095fdc4093727c16 100644 (file)
   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
index 7d00f4eb256631703174062f87896e42f6d10313..8e717ada28d0a4c14e9718f7e573503757cb34af 100644 (file)
@@ -323,7 +323,6 @@ typedef struct ForeignTruncateInfo
 {
    Oid         serverid;
    List       *rels;
-   List       *rels_extra;
 } ForeignTruncateInfo;
 
 /*
@@ -1620,7 +1619,6 @@ ExecuteTruncate(TruncateStmt *stmt)
 {
    List       *rels = NIL;
    List       *relids = NIL;
-   List       *relids_extra = NIL;
    List       *relids_logged = NIL;
    ListCell   *cell;
 
@@ -1654,9 +1652,7 @@ ExecuteTruncate(TruncateStmt *stmt)
 
        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);
@@ -1704,8 +1700,7 @@ ExecuteTruncate(TruncateStmt *stmt)
 
                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);
@@ -1718,7 +1713,7 @@ ExecuteTruncate(TruncateStmt *stmt)
                     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 */
@@ -1739,15 +1734,13 @@ ExecuteTruncate(TruncateStmt *stmt)
  *
  * 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)
 {
@@ -1760,8 +1753,6 @@ ExecuteTruncateGuts(List *explicit_rels,
    ResultRelInfo *resultRelInfo;
    SubTransactionId mySubid;
    ListCell   *cell;
-   ListCell   *lc1,
-           *lc2;
    Oid        *logrelids;
 
    /*
@@ -1799,8 +1790,7 @@ ExecuteTruncateGuts(List *explicit_rels,
                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);
@@ -1901,11 +1891,9 @@ ExecuteTruncateGuts(List *explicit_rels,
     */
    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
@@ -1952,7 +1940,6 @@ ExecuteTruncateGuts(List *explicit_rels,
            {
                ft_info->serverid = serverid;
                ft_info->rels = NIL;
-               ft_info->rels_extra = NIL;
            }
 
            /*
@@ -1960,7 +1947,6 @@ ExecuteTruncateGuts(List *explicit_rels,
             * foreign table belongs to.
             */
            ft_info->rels = lappend(ft_info->rels, rel);
-           ft_info->rels_extra = lappend_int(ft_info->rels_extra, extra);
            continue;
        }
 
@@ -2044,7 +2030,6 @@ ExecuteTruncateGuts(List *explicit_rels,
                Assert(routine->ExecForeignTruncate != NULL);
 
                routine->ExecForeignTruncate(ft_info->rels,
-                                            ft_info->rels_extra,
                                             behavior,
                                             restart_seqs);
            }
index d09703f7acd1f53faf22cdb345216bf20254cdda..d9f157172b2347120e4df3a9f12ab5dcd864ca9b 100644 (file)
@@ -1816,7 +1816,6 @@ apply_handle_truncate(StringInfo s)
    List       *rels = NIL;
    List       *part_rels = NIL;
    List       *relids = NIL;
-   List       *relids_extra = NIL;
    List       *relids_logged = NIL;
    ListCell   *lc;
 
@@ -1846,7 +1845,6 @@ apply_handle_truncate(StringInfo s)
        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);
 
@@ -1885,7 +1883,6 @@ apply_handle_truncate(StringInfo s)
                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);
@@ -1900,7 +1897,6 @@ apply_handle_truncate(StringInfo s)
     */
    ExecuteTruncateGuts(rels,
                        relids,
-                       relids_extra,
                        relids_logged,
                        DROP_RESTRICT,
                        restart_seqs);
index b808a07e461b63ea22c514bd220b4558bc42697e..14f4b4882ff6670aed2dbdd2c686b37db11ecf8e 100644 (file)
 #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 */
 
 
@@ -68,7 +58,6 @@ extern void CheckTableNotInUse(Relation rel, const char *stmt);
 extern void ExecuteTruncate(TruncateStmt *stmt);
 extern void ExecuteTruncateGuts(List *explicit_rels,
                                List *relids,
-                               List *relids_extra,
                                List *relids_logged,
                                DropBehavior behavior,
                                bool restart_seqs);
index 4ebbca6de920b9ca37a78cdb082f9c93ca6c8153..4f17becbb81c1b930c038f6146821b6267f072d2 100644 (file)
@@ -161,7 +161,6 @@ typedef List *(*ImportForeignSchema_function) (ImportForeignSchemaStmt *stmt,
                                               Oid serverOid);
 
 typedef void (*ExecForeignTruncate_function) (List *rels,
-                                             List *rels_extra,
                                              DropBehavior behavior,
                                              bool restart_seqs);