Skip to content

Commit 8e9ea08

Browse files
committed
Don't pass "ONLY" options specified in TRUNCATE to foreign data wrapper.
Commit 8ff1c94 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
1 parent 3fa17d3 commit 8e9ea08

File tree

11 files changed

+60
-83
lines changed

11 files changed

+60
-83
lines changed

contrib/postgres_fdw/deparse.c

+4-9
Original file line numberDiff line numberDiff line change
@@ -2179,24 +2179,19 @@ deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
21792179
void
21802180
deparseTruncateSql(StringInfo buf,
21812181
List *rels,
2182-
List *rels_extra,
21832182
DropBehavior behavior,
21842183
bool restart_seqs)
21852184
{
2186-
ListCell *lc1,
2187-
*lc2;
2185+
ListCell *cell;
21882186

21892187
appendStringInfoString(buf, "TRUNCATE ");
21902188

2191-
forboth(lc1, rels, lc2, rels_extra)
2189+
foreach(cell, rels)
21922190
{
2193-
Relation rel = lfirst(lc1);
2194-
int extra = lfirst_int(lc2);
2191+
Relation rel = lfirst(cell);
21952192

2196-
if (lc1 != list_head(rels))
2193+
if (cell != list_head(rels))
21972194
appendStringInfoString(buf, ", ");
2198-
if (extra & TRUNCATE_REL_CONTEXT_ONLY)
2199-
appendStringInfoString(buf, "ONLY ");
22002195

22012196
deparseRelation(buf, rel);
22022197
}

contrib/postgres_fdw/expected/postgres_fdw.out

+15-9
Original file line numberDiff line numberDiff line change
@@ -8218,13 +8218,13 @@ drop table loc3;
82188218
-- test for TRUNCATE
82198219
-- ===================================================================
82208220
CREATE TABLE tru_rtable0 (id int primary key);
8221-
CREATE TABLE tru_rtable1 (id int primary key);
82228221
CREATE FOREIGN TABLE tru_ftable (id int)
82238222
SERVER loopback OPTIONS (table_name 'tru_rtable0');
82248223
INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
82258224
CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
82268225
CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
82278226
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
8227+
CREATE TABLE tru_rtable1 (id int primary key);
82288228
CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
82298229
FOR VALUES WITH (MODULUS 2, REMAINDER 1)
82308230
SERVER loopback OPTIONS (table_name 'tru_rtable1');
@@ -8364,6 +8364,8 @@ SELECT count(*) from tru_pk_ftable; -- 0
83648364
(1 row)
83658365

83668366
-- truncate with ONLY clause
8367+
-- Since ONLY is specified, the table tru_ftable_child that inherits
8368+
-- tru_ftable_parent locally is not truncated.
83678369
TRUNCATE ONLY tru_ftable_parent;
83688370
SELECT sum(id) FROM tru_ftable_parent; -- 126
83698371
sum
@@ -8388,22 +8390,26 @@ SELECT sum(id) FROM tru_ftable; -- 95
83888390
95
83898391
(1 row)
83908392

8391-
TRUNCATE ONLY tru_ftable; -- truncate only parent portion
8392-
SELECT sum(id) FROM tru_ftable; -- 60
8393-
sum
8394-
-----
8395-
60
8393+
-- Both parent and child tables in the foreign server are truncated
8394+
-- even though ONLY is specified because ONLY has no effect
8395+
-- when truncating a foreign table.
8396+
TRUNCATE ONLY tru_ftable;
8397+
SELECT count(*) FROM tru_ftable; -- 0
8398+
count
8399+
-------
8400+
0
83968401
(1 row)
83978402

83988403
INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
8399-
SELECT sum(id) FROM tru_ftable; -- 175
8404+
INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
8405+
SELECT sum(id) FROM tru_ftable; -- 255
84008406
sum
84018407
-----
8402-
175
8408+
255
84038409
(1 row)
84048410

84058411
TRUNCATE tru_ftable; -- truncate both of parent and child
8406-
SELECT count(*) FROM tru_ftable; -- empty
8412+
SELECT count(*) FROM tru_ftable; -- 0
84078413
count
84088414
-------
84098415
0

contrib/postgres_fdw/postgres_fdw.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ static void postgresExplainForeignModify(ModifyTableState *mtstate,
401401
static void postgresExplainDirectModify(ForeignScanState *node,
402402
ExplainState *es);
403403
static void postgresExecForeignTruncate(List *rels,
404-
List *rels_extra,
405404
DropBehavior behavior,
406405
bool restart_seqs);
407406
static bool postgresAnalyzeForeignTable(Relation relation,
@@ -2881,7 +2880,6 @@ postgresExplainDirectModify(ForeignScanState *node, ExplainState *es)
28812880
*/
28822881
static void
28832882
postgresExecForeignTruncate(List *rels,
2884-
List *rels_extra,
28852883
DropBehavior behavior,
28862884
bool restart_seqs)
28872885
{
@@ -2964,7 +2962,7 @@ postgresExecForeignTruncate(List *rels,
29642962

29652963
/* Construct the TRUNCATE command string */
29662964
initStringInfo(&sql);
2967-
deparseTruncateSql(&sql, rels, rels_extra, behavior, restart_seqs);
2965+
deparseTruncateSql(&sql, rels, behavior, restart_seqs);
29682966

29692967
/* Issue the TRUNCATE command to remote server */
29702968
do_sql_command(conn, sql.data);

contrib/postgres_fdw/postgres_fdw.h

-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
209209
List **retrieved_attrs);
210210
extern void deparseTruncateSql(StringInfo buf,
211211
List *rels,
212-
List *rels_extra,
213212
DropBehavior behavior,
214213
bool restart_seqs);
215214
extern void deparseStringLiteral(StringInfo buf, const char *val);

contrib/postgres_fdw/sql/postgres_fdw.sql

+11-5
Original file line numberDiff line numberDiff line change
@@ -2355,14 +2355,14 @@ drop table loc3;
23552355
-- test for TRUNCATE
23562356
-- ===================================================================
23572357
CREATE TABLE tru_rtable0 (id int primary key);
2358-
CREATE TABLE tru_rtable1 (id int primary key);
23592358
CREATE FOREIGN TABLE tru_ftable (id int)
23602359
SERVER loopback OPTIONS (table_name 'tru_rtable0');
23612360
INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
23622361

23632362
CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
23642363
CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
23652364
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
2365+
CREATE TABLE tru_rtable1 (id int primary key);
23662366
CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
23672367
FOR VALUES WITH (MODULUS 2, REMAINDER 1)
23682368
SERVER loopback OPTIONS (table_name 'tru_rtable1');
@@ -2428,6 +2428,8 @@ SELECT count(*) from tru_ftable; -- 0
24282428
SELECT count(*) from tru_pk_ftable; -- 0
24292429

24302430
-- truncate with ONLY clause
2431+
-- Since ONLY is specified, the table tru_ftable_child that inherits
2432+
-- tru_ftable_parent locally is not truncated.
24312433
TRUNCATE ONLY tru_ftable_parent;
24322434
SELECT sum(id) FROM tru_ftable_parent; -- 126
24332435
TRUNCATE tru_ftable_parent;
@@ -2439,13 +2441,17 @@ INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x);
24392441
INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(10,14) x);
24402442
SELECT sum(id) FROM tru_ftable; -- 95
24412443

2442-
TRUNCATE ONLY tru_ftable; -- truncate only parent portion
2443-
SELECT sum(id) FROM tru_ftable; -- 60
2444+
-- Both parent and child tables in the foreign server are truncated
2445+
-- even though ONLY is specified because ONLY has no effect
2446+
-- when truncating a foreign table.
2447+
TRUNCATE ONLY tru_ftable;
2448+
SELECT count(*) FROM tru_ftable; -- 0
24442449

24452450
INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
2446-
SELECT sum(id) FROM tru_ftable; -- 175
2451+
INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
2452+
SELECT sum(id) FROM tru_ftable; -- 255
24472453
TRUNCATE tru_ftable; -- truncate both of parent and child
2448-
SELECT count(*) FROM tru_ftable; -- empty
2454+
SELECT count(*) FROM tru_ftable; -- 0
24492455

24502456
-- cleanup
24512457
DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable__p1,tru_ftable;

doc/src/sgml/fdwhandler.sgml

+13-16
Original file line numberDiff line numberDiff line change
@@ -1071,28 +1071,16 @@ EndDirectModify(ForeignScanState *node);
10711071
<para>
10721072
<programlisting>
10731073
void
1074-
ExecForeignTruncate(List *rels, List *rels_extra,
1075-
DropBehavior behavior, bool restart_seqs);
1074+
ExecForeignTruncate(List *rels,
1075+
DropBehavior behavior,
1076+
bool restart_seqs);
10761077
</programlisting>
10771078

10781079
Truncate a set of foreign tables specified in <literal>rels</literal>.
10791080
This function is called when <xref linkend="sql-truncate"/> is executed
10801081
on foreign tables. <literal>rels</literal> is the list of
10811082
<structname>Relation</structname> data structure that indicates
1082-
a foreign table to truncate. <literal>rels_extra</literal> the list of
1083-
<literal>int</literal> value, which delivers extra information about
1084-
a foreign table to truncate. Possible values are
1085-
<literal>TRUNCATE_REL_CONTEXT_NORMAL</literal>, which means that
1086-
the foreign table is specified WITHOUT <literal>ONLY</literal> clause
1087-
in <command>TRUNCATE</command>,
1088-
<literal>TRUNCATE_REL_CONTEXT_ONLY</literal>, which means that
1089-
the foreign table is specified WITH <literal>ONLY</literal> clause,
1090-
and <literal>TRUNCATE_REL_CONTEXT_CASCADING</literal>,
1091-
which means that the foreign table is not specified explicitly,
1092-
but will be truncated due to dependency (for example, partition table).
1093-
There is one-to-one mapping between <literal>rels</literal> and
1094-
<literal>rels_extra</literal>. The number of entries is the same
1095-
between the two lists.
1083+
a foreign table to truncate.
10961084
</para>
10971085

10981086
<para>
@@ -1111,6 +1099,15 @@ ExecForeignTruncate(List *rels, List *rels_extra,
11111099
if <literal>CONTINUE IDENTITY</literal> option is specified.
11121100
</para>
11131101

1102+
<para>
1103+
Note that the <literal>ONLY</literal> options specified
1104+
in the original <command>TRUNCATE</command> command are not passed to
1105+
<function>ExecForeignTruncate</function>. This behavior is similar to
1106+
the callback functions of <command>SELECT</command>,
1107+
<command>UPDATE</command> and <command>DELETE</command> on
1108+
a foreign table.
1109+
</para>
1110+
11141111
<para>
11151112
<command>TRUNCATE</command> invokes
11161113
<function>ExecForeignTruncate</function> once per foreign server

doc/src/sgml/postgres-fdw.sgml

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@
6969
have privileges to do these things.)
7070
</para>
7171

72+
<para>
73+
Note that the <literal>ONLY</literal> option specified in
74+
<command>SELECT</command>, <command>UPDATE</command>,
75+
<command>DELETE</command> or <command>TRUNCATE</command>
76+
has no effect when accessing or modifying the remote table.
77+
</para>
78+
7279
<para>
7380
Note that <filename>postgres_fdw</filename> currently lacks support for
7481
<command>INSERT</command> statements with an <literal>ON CONFLICT DO

src/backend/commands/tablecmds.c

+9-24
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ typedef struct ForeignTruncateInfo
323323
{
324324
Oid serverid;
325325
List *rels;
326-
List *rels_extra;
327326
} ForeignTruncateInfo;
328327

329328
/*
@@ -1620,7 +1619,6 @@ ExecuteTruncate(TruncateStmt *stmt)
16201619
{
16211620
List *rels = NIL;
16221621
List *relids = NIL;
1623-
List *relids_extra = NIL;
16241622
List *relids_logged = NIL;
16251623
ListCell *cell;
16261624

@@ -1654,9 +1652,7 @@ ExecuteTruncate(TruncateStmt *stmt)
16541652

16551653
rels = lappend(rels, rel);
16561654
relids = lappend_oid(relids, myrelid);
1657-
relids_extra = lappend_int(relids_extra, (recurse ?
1658-
TRUNCATE_REL_CONTEXT_NORMAL :
1659-
TRUNCATE_REL_CONTEXT_ONLY));
1655+
16601656
/* Log this relation only if needed for logical decoding */
16611657
if (RelationIsLogicallyLogged(rel))
16621658
relids_logged = lappend_oid(relids_logged, myrelid);
@@ -1704,8 +1700,7 @@ ExecuteTruncate(TruncateStmt *stmt)
17041700

17051701
rels = lappend(rels, rel);
17061702
relids = lappend_oid(relids, childrelid);
1707-
relids_extra = lappend_int(relids_extra,
1708-
TRUNCATE_REL_CONTEXT_CASCADING);
1703+
17091704
/* Log this relation only if needed for logical decoding */
17101705
if (RelationIsLogicallyLogged(rel))
17111706
relids_logged = lappend_oid(relids_logged, childrelid);
@@ -1718,7 +1713,7 @@ ExecuteTruncate(TruncateStmt *stmt)
17181713
errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
17191714
}
17201715

1721-
ExecuteTruncateGuts(rels, relids, relids_extra, relids_logged,
1716+
ExecuteTruncateGuts(rels, relids, relids_logged,
17221717
stmt->behavior, stmt->restart_seqs);
17231718

17241719
/* And close the rels */
@@ -1739,15 +1734,13 @@ ExecuteTruncate(TruncateStmt *stmt)
17391734
*
17401735
* explicit_rels is the list of Relations to truncate that the command
17411736
* specified. relids is the list of Oids corresponding to explicit_rels.
1742-
* relids_extra is the list of integer values that deliver extra information
1743-
* about relations in explicit_rels. relids_logged is the list of Oids
1744-
* (a subset of relids) that require WAL-logging. This is all a bit redundant,
1745-
* but the existing callers have this information handy in this form.
1737+
* relids_logged is the list of Oids (a subset of relids) that require
1738+
* WAL-logging. This is all a bit redundant, but the existing callers have
1739+
* this information handy in this form.
17461740
*/
17471741
void
17481742
ExecuteTruncateGuts(List *explicit_rels,
17491743
List *relids,
1750-
List *relids_extra,
17511744
List *relids_logged,
17521745
DropBehavior behavior, bool restart_seqs)
17531746
{
@@ -1760,8 +1753,6 @@ ExecuteTruncateGuts(List *explicit_rels,
17601753
ResultRelInfo *resultRelInfo;
17611754
SubTransactionId mySubid;
17621755
ListCell *cell;
1763-
ListCell *lc1,
1764-
*lc2;
17651756
Oid *logrelids;
17661757

17671758
/*
@@ -1799,8 +1790,7 @@ ExecuteTruncateGuts(List *explicit_rels,
17991790
truncate_check_activity(rel);
18001791
rels = lappend(rels, rel);
18011792
relids = lappend_oid(relids, relid);
1802-
relids_extra = lappend_int(relids_extra,
1803-
TRUNCATE_REL_CONTEXT_CASCADING);
1793+
18041794
/* Log this relation only if needed for logical decoding */
18051795
if (RelationIsLogicallyLogged(rel))
18061796
relids_logged = lappend_oid(relids_logged, relid);
@@ -1901,11 +1891,9 @@ ExecuteTruncateGuts(List *explicit_rels,
19011891
*/
19021892
mySubid = GetCurrentSubTransactionId();
19031893

1904-
Assert(list_length(rels) == list_length(relids_extra));
1905-
forboth(lc1, rels, lc2, relids_extra)
1894+
foreach(cell, rels)
19061895
{
1907-
Relation rel = (Relation) lfirst(lc1);
1908-
int extra = lfirst_int(lc2);
1896+
Relation rel = (Relation) lfirst(cell);
19091897

19101898
/*
19111899
* Save OID of partitioned tables for later; nothing else to do for
@@ -1952,15 +1940,13 @@ ExecuteTruncateGuts(List *explicit_rels,
19521940
{
19531941
ft_info->serverid = serverid;
19541942
ft_info->rels = NIL;
1955-
ft_info->rels_extra = NIL;
19561943
}
19571944

19581945
/*
19591946
* Save the foreign table in the entry of the server that the
19601947
* foreign table belongs to.
19611948
*/
19621949
ft_info->rels = lappend(ft_info->rels, rel);
1963-
ft_info->rels_extra = lappend_int(ft_info->rels_extra, extra);
19641950
continue;
19651951
}
19661952

@@ -2044,7 +2030,6 @@ ExecuteTruncateGuts(List *explicit_rels,
20442030
Assert(routine->ExecForeignTruncate != NULL);
20452031

20462032
routine->ExecForeignTruncate(ft_info->rels,
2047-
ft_info->rels_extra,
20482033
behavior,
20492034
restart_seqs);
20502035
}

src/backend/replication/logical/worker.c

-4
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,6 @@ apply_handle_truncate(StringInfo s)
18161816
List *rels = NIL;
18171817
List *part_rels = NIL;
18181818
List *relids = NIL;
1819-
List *relids_extra = NIL;
18201819
List *relids_logged = NIL;
18211820
ListCell *lc;
18221821

@@ -1846,7 +1845,6 @@ apply_handle_truncate(StringInfo s)
18461845
remote_rels = lappend(remote_rels, rel);
18471846
rels = lappend(rels, rel->localrel);
18481847
relids = lappend_oid(relids, rel->localreloid);
1849-
relids_extra = lappend_int(relids_extra, TRUNCATE_REL_CONTEXT_NORMAL);
18501848
if (RelationIsLogicallyLogged(rel->localrel))
18511849
relids_logged = lappend_oid(relids_logged, rel->localreloid);
18521850

@@ -1885,7 +1883,6 @@ apply_handle_truncate(StringInfo s)
18851883
rels = lappend(rels, childrel);
18861884
part_rels = lappend(part_rels, childrel);
18871885
relids = lappend_oid(relids, childrelid);
1888-
relids_extra = lappend_int(relids_extra, TRUNCATE_REL_CONTEXT_CASCADING);
18891886
/* Log this relation only if needed for logical decoding */
18901887
if (RelationIsLogicallyLogged(childrel))
18911888
relids_logged = lappend_oid(relids_logged, childrelid);
@@ -1900,7 +1897,6 @@ apply_handle_truncate(StringInfo s)
19001897
*/
19011898
ExecuteTruncateGuts(rels,
19021899
relids,
1903-
relids_extra,
19041900
relids_logged,
19051901
DROP_RESTRICT,
19061902
restart_seqs);

0 commit comments

Comments
 (0)