Re: TRUNCATE on foreign tables

From: Michael Paquier <michael(at)paquier(dot)xyz>
To: Kohei KaiGai <kaigai(at)heterodb(dot)com>
Cc: Stephen Frost <sfrost(at)snowman(dot)net>, Alvaro Herrera <alvherre(at)2ndquadrant(dot)com>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: TRUNCATE on foreign tables
Date: 2020-01-15 08:11:26
Message-ID: 20200115081126.GK2243@paquier.xyz
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, Jan 14, 2020 at 06:16:17PM +0900, Kohei KaiGai wrote:
> The "frels_list" is a list of foreign tables that are connected to a particular
> foreign server, thus, the server-id pulled out by foreign tables id should be
> identical for all the relations in the list.
> Due to the API design, this callback shall be invoked for each foreign server
> involved in the TRUNCATE command, not per table basis.
>
> The 2nd and 3rd arguments also informs FDW driver other options of the
> command. If FDW has a concept of "cascaded truncate" or "restart sequence",
> it can adjust its remote query. In postgres_fdw, it follows the manner of
> usual TRUNCATE command.

I have done a quick read through the patch. You have modified the
patch to pass down to the callback a list of relation OIDs to execute
one command for all, and there are tests for FKs so that coverage
looks fine.

Regression tests are failing with this patch:
-- TRUNCATE doesn't work on foreign tables, either directly or
recursively
TRUNCATE ft2; -- ERROR
-ERROR: "ft2" is not a table
+ERROR: foreign-data wrapper "dummy" has no handler
You visibly just need to update the output because no handlers are
available for truncate in this case.

+void
+deparseTruncateSql(StringInfo buf, Relation rel)
+{
+ deparseRelation(buf, rel);
+}
Don't see much point in having this routine.

+ If FDW does not provide this callback, PostgreSQL considers
+ <command>TRUNCATE</command> is not supported on the foreign table.
+ </para>
This sentence is weird. Perhaps you meant "as not supported"?

+ <literal>frels_list</literal> is a list of foreign tables that are
+ connected to a particular foreign server; thus, these foreign tables
+ should have identical foreign server ID
The list is built by the backend code, so that has to be true.

+ foreach (lc, frels_list)
+ {
+ Relation frel = lfirst(lc);
+ Oid frel_oid = RelationGetRelid(frel);
+
+ if (server_id == GetForeignServerIdByRelId(frel_oid))
+ {
+ frels_list = foreach_delete_current(frels_list, lc);
+ curr_frels = lappend(curr_frels, frel);
+ }
+ }
Wouldn't it be better to fill in a hash table for each server with a
list of relations?

+typedef void (*ExecForeignTruncate_function) (List *frels_list,
+ bool is_cascade,
+ bool restart_seqs);
I would recommend to pass down directly DropBehavior instead of a
boolean to the callback. That's more extensible.
--
Michael

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Kyotaro Horiguchi 2020-01-15 08:18:57 Re: [HACKERS] WAL logging problem in 9.4.3?
Previous Message Andres Freund 2020-01-15 07:27:02 Re: aggregate crash