Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vdQLm-000LqS-0E for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Jan 2026 10:01:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vdQLk-00DQZ8-2U for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Jan 2026 10:01:09 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vdQLk-00DQYz-1G for pgsql-hackers@lists.postgresql.org; Wed, 07 Jan 2026 10:01:09 +0000 Received: from mail-qt1-x833.google.com ([2607:f8b0:4864:20::833]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vdQLi-0053jn-1R for pgsql-hackers@postgresql.org; Wed, 07 Jan 2026 10:01:08 +0000 Received: by mail-qt1-x833.google.com with SMTP id d75a77b69052e-4f1ab2ea5c1so24871911cf.3 for ; Wed, 07 Jan 2026 02:01:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767780064; x=1768384864; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=P1utrb2rQo2293aHGzWNtArL+8RDiRJRDNWB9jtmSLU=; b=QQYaeGe4Be4FRTGBxxfOi0GCghPLISE87BzMRUQwwavMKzkfj0pTV/qmSR32dR1nUh ShNDejYAqEsdun76YSixVvvSwjbj0nJxj7QNINtxgdhYc2x4KsaoEVsgrgtqtK6O1L46 /I0+O0Stthy7BJ1kEfBN/7zoIxEC1Knhc34JkTvZJwjqm1HWXeRnqOCkBK2BB3ve832L Xk2u0HQ/XmjnGgw9SZOegMxarHqcGYwK92XecCIJNYT/tzJ8K/5BvxaSzde6KGbW2R1K WPBEMTFH2XrV4RLUHi08C2EpzW7VqZeCZWzVRE2BEXa3AmhKwJxS7bnci+5cEq4tIzEQ s6oQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767780064; x=1768384864; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=P1utrb2rQo2293aHGzWNtArL+8RDiRJRDNWB9jtmSLU=; b=i3hRL8RBcacYLHZkeMimwCMQABtSbQych9HwUmsJD3yWitjJ7BNjVKAfXfo5Rxb48J QUwsWb86LilhQh9u/T95xcDH/h35ptkO9R6BqrW0M5DMRNRpgJT7HHcCuLCX3g+Uace5 zAj/1BHwpOYlG9VAJi1J6Q/YLOoUwVSA+GtpLQDEj0v3hiHDbnavomCqkYK0BKt/5zom JippHhANjPF848LQs2RvuJGTImEWJ6P1P7s3GQquAyHZRrs/NMMSxo0nSfvycajyJgJR HUgJ1UqjI51rVk7SqHUF5HWwexp5digL4+xwC3Ko6qReN/JHs7wGN6XN+A1pfnShPu8q 4OQw== X-Forwarded-Encrypted: i=1; AJvYcCWNuAMSN0by/ITqgQMjtI22lzs193REsnpLO5gYtzEZVdbqbAuv7gu2qph571q6WrEm+i5gBZLY1Eb3wcnW@postgresql.org X-Gm-Message-State: AOJu0YwPoDJkDWtggBfGO3hT7/Cfqy+nleoEUTK9lc/ltfEN5QHf07wO PQNavfjfXjqqI+JDTCa9g/CybQrOeeNNDVo1I1WewDpnfofUT0aLkoZk5T1ewgXuYCUYYdq6yUF XXrO/hLk0uMU9RhgWkWXeaLAAzKRuEzQD6p0k X-Gm-Gg: AY/fxX4Mggq6XDNMwjAg0cdvEzMm7ntS5wcDYq6EKn8Mj0H4F+L2UfVKZWI8CT1Z36P XZCu0VkACWtB6ZZXvT7RT8K3pbOwt802IvHjbACi35Ma3iiw6a+BoDU7h8/2T9D9RLnqxuBMjso A8gGqYyL+G+LITFWfaJxFZPJXhUCtLENtDHXU1rGgAOOk3uoMH8DuIPq/uAEN/3zlCSrECoWUTp 5/L47p3fFIZ+ujvfRT+/9URlM69Z9d27ZowRVMPthM7NmsxzeRrQvRdmODCOMq1eJIPm0fJ X-Google-Smtp-Source: AGHT+IH9GKlCaN5Gdl4vO/g+YA0kCinF8tsDuauYA0/BmDDERXLreANRC+zBEd0D7akkYsNg1fKslzSJsvaln5snLv8= X-Received: by 2002:a05:622a:2489:b0:4ed:dec2:301a with SMTP id d75a77b69052e-4ffb484a72emr25137471cf.16.1767780064222; Wed, 07 Jan 2026 02:01:04 -0800 (PST) MIME-Version: 1.0 References: <07147023882ac6c4424df946fd4b82b8e8c211a5.camel@j-davis.com> <341357.1741201933@sss.pgh.pa.us> In-Reply-To: From: dinesh salve Date: Wed, 7 Jan 2026 15:30:25 +0530 X-Gm-Features: AQt7F2qdbOg-eQuFG45lfK7Rj5XAkyJttLh1y2Lv_I3Hl8c5IGx_lXV26JkFJlw Message-ID: Subject: Re: explain plans for foreign servers To: Sami Imseih Cc: Tom Lane , pgsql-hackers@postgresql.org, Jeff Davis Content-Type: multipart/alternative; boundary="000000000000c4e05c0647c95e44" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000c4e05c0647c95e44 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks Sami for feedback. Few points I wanted to call out and need your inputs on - Supporting remote_plans options for inserts: Only "explain insert" are executed with bind variables (verified by logging all sqls while running make check) and while executing that on remote is erroring out with error "there is no parameter $1". We can either NOT support remote plans for insert statements or always use generic_plan option on remote sql. Using "generic_plan" on remote comes with an additional check if remote supports this option or not in case remote shard is older postgres. I prefer not supporting remote_plans for inserts as there is nothing much that goes in insert statement plans unless its "insert into..select". User can always run explain on that select separately. Appreciate your inputs on this. About decision which explain options we should forward to remote shard: This is because local and remote postgres could be different and we still need to address what all options we send in remote sql as remote shard might not even support them. We can forward only limited options to remote which are widely supported (pg >=3D 9) i.e. verbose, costs, buffers, format only. If we need to support all possible options, we need to query the version of remote postgres and then prepare remote sql. Thoughts? Regard, Dinesh (AWS) On Wed, Dec 10, 2025 at 2:38=E2=80=AFAM Sami Imseih w= rote: > Hi, > > I spent more time reviewing this patch. Here are additional comments. > > 1/ Remove unnecessary includes > > #include "commands/explain_state.h" from option.c. > #include "utils/json.h" from postgres_fdw.c. > > 2/ Add new EXPLAIN options > > MEMORY and SUMMARY flags added to the remote EXPLAIN query formatting. > These do not require ANALYZE to be used. > > A larger question is how would we want to ensure that new core EXPLAIN > options can be automatically set? > > This is not quite common, but perhaps it is a good thing to add a comment > near ExplainState explaining that if a new option is added, make sure > that postgre_fdw remote_plans are updated. > > ``` > typedef struct ExplainState > { > StringInfo str; /* output buffer */ > /* options */ > bool verbose; /* be verbose */ > bool analyze; /* print actual times */ > bool costs; /* print estimated co > > ``` > > 3/ Removed unnecessary pstrdup() when appending remote plan rows to > explain_plan. > > Removed unnecessary pstrdup() when appending remote plan rows to > explain_plan. > > ``` > + appendStringInfo(&explain->explain_plan, > "%s\n", pstrdup(PQgetvalue(res, i, 0))); > ``` > > > 4/ Simplify foreign table OID handling in postgresExplainForeignScan > > I am not sure why we need a list that can only hold a single value. > Can we just use an Oid variable to store this? > > > 5/ Encapsulates getting the connection, executing the remote EXPLAIN, > and releasing the connection. > > Replaces repeated code in postgresExplainForeignScan, > postgresExplainForeignModify, and postgresExplainDirectModify. > > For #4 and #5, attached is my attempt to simplify these routines. What > do you think? > > 6/ Updated typedefs.list > > ... to include PgFdwExplainRemotePlans and PgFdwExplainState. > > > 7/ Tests > > I quickly skimmed the tests, but I did not see a join push-down test. > We should add > that. > > > -- > Sami Imseih > Amazon Web Services (AWS) --000000000000c4e05c0647c95e44 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Thanks=C2=A0Sami for feedback. Few points= I wanted to call out and need your inputs on -=C2=A0

Su= pporting=C2=A0remote_plans options for inserts:
Only "explai= n insert" are executed with bind variables (verified by logging all sq= ls while running make check) and while executing that on remote is erroring= out with error "there is no parameter $1". We can either NOT sup= port remote plans for insert statements or always use generic_plan option o= n remote sql. Using "generic_plan" on remote comes with=C2=A0an a= dditional check if remote supports this option or not in case remote shard = is older postgres.
I prefer not supporting remote_plans for inser= ts as there is nothing much that goes in insert statement plans unless its = "insert into..select". User can always run explain on that select= separately. Appreciate your inputs=C2=A0on this.

= About decision=C2=A0which=C2=A0explain options we should forward to remote = shard:
This is because local and remote postgres could be differe= nt and we still need to address what all options we send in remote sql as r= emote shard might not even support them. We can forward only limited option= s to remote which are widely supported (pg >=3D 9) i.e. verbose, costs, = buffers, format only.
If we need to support all possible options, we n= eed to query the version of remote postgres and then prepare remote sql. Th= oughts?

Regard,
Dinesh (AWS)

On Wed, Dec 10, 2025 at 2:38=E2=80=AFAM Sami Imseih <samimseih@gmail.com> wrote:
Hi,

I spent more time reviewing this patch. Here are additional comments.

1/ Remove unnecessary includes

#include "commands/explain_state.h" from option.c.
#include "utils/json.h" from postgres_fdw.c.

2/ Add new EXPLAIN options

MEMORY and SUMMARY flags added to the remote EXPLAIN query formatting.
These do not require ANALYZE to be used.

A larger question is how would we want to ensure that new core EXPLAIN
options can be automatically set?

This is not quite common, but perhaps it is a good thing to add a comment near ExplainState explaining that if a new option is added, make sure
that postgre_fdw remote_plans are updated.

```
typedef struct ExplainState
{
=C2=A0 StringInfo=C2=A0 str;=C2=A0 =C2=A0 =C2=A0 /* output buffer */
=C2=A0 /* options */
=C2=A0 bool=C2=A0 =C2=A0 verbose;=C2=A0 =C2=A0 /* be verbose */
=C2=A0 bool=C2=A0 =C2=A0 analyze;=C2=A0 =C2=A0 /* print actual times */
=C2=A0 bool=C2=A0 =C2=A0 costs;=C2=A0 =C2=A0 =C2=A0 /* print estimated co
```

3/ Removed unnecessary pstrdup() when appending remote plan rows to
explain_plan.

Removed unnecessary pstrdup() when appending remote plan rows to explain_pl= an.

```
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0appendStringInfo(&explain->explain_plan,
"%s\n", pstrdup(PQgetvalue(res, i, 0)));
```


4/ Simplify foreign table OID handling in postgresExplainForeignScan

I am not sure why we need a list that can only hold a single value.
Can we just use an Oid variable to store this?


5/ Encapsulates getting the connection, executing the remote EXPLAIN,
and releasing the connection.

Replaces repeated code in postgresExplainForeignScan,
postgresExplainForeignModify, and postgresExplainDirectModify.

For #4 and #5, attached is my attempt to simplify these routines. What
do you think?

6/ Updated typedefs.list

... to include PgFdwExplainRemotePlans and PgFdwExplainState.


7/ Tests

I quickly skimmed the tests, but I did not see a join push-down test.
We should add
that.


--
Sami Imseih
Amazon Web Services (AWS)
--000000000000c4e05c0647c95e44--