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 1veMev-00CPat-28 for pgsql-hackers@arkaria.postgresql.org; Sat, 10 Jan 2026 00:16:50 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1veMes-0095B4-1I for pgsql-hackers@arkaria.postgresql.org; Sat, 10 Jan 2026 00:16:47 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1veMer-0095Av-32 for pgsql-hackers@lists.postgresql.org; Sat, 10 Jan 2026 00:16:46 +0000 Received: from mail-ed1-x532.google.com ([2a00:1450:4864:20::532]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1veMer-0059ad-0i for pgsql-hackers@postgresql.org; Sat, 10 Jan 2026 00:16:45 +0000 Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-64ba74e6892so7914253a12.2 for ; Fri, 09 Jan 2026 16:16:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768004198; x=1768608998; 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=OWxMfUba8TNDNjCOwoUU1YciX2nN+/4d6YdTeGaVrN0=; b=U7gjSfN9sNtr9dibXG4bmNggJAg5ZAUK0n0luC9H0E0//w1N1vnRyMbMj1IxPD1MBd 4ceE+b4EVcDVG/s4fhfVAcPcPAqx40AW2/vuCZPxDKLWz/LrUm4fTOtrfVKf4tnc64PP 7bnpNmmIMr0SwzhWwAPSzTtzpo//juTZgoRTOzTyaJ8nez9PC9JMH3N6Der2AoXAagyj 8NIQf0H3XxqHw/vw6t01TfjONSpcu/xK2hhQVF8pJW8bD/sLAssxhCXGQOIx1z6z050v UkOR3mJehf57bwP9mhO1vYDSAt45X9SNOntwXUyxULFrA8W6DRzg8UaeWX1IlT75z3qw 8quA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768004198; x=1768608998; 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=OWxMfUba8TNDNjCOwoUU1YciX2nN+/4d6YdTeGaVrN0=; b=f4CLP7tOT6kPbTZxEP0SKAYgek9oMyA3HjuWWWKcZQOtdQ6DoqfNY6sSJTjnj406Fr cmWUalhUhEVuxEqA3M/+yOmRnVVTPqM/w0VAPIcf9Kqm4qAqlE1wVJMp9+WrHbavGiai pijxNy/SKlClbkJjqVjZe1B+90WXQNzdQlpR3X8/uQfOd0V2kKJIkmkL4vGGajbITvOF hlUXJc6lnU+dJRmjWR98vLDsHNcxKDfVE9VXrVgJWB85zmJNLOpb7E0us7r0PEmklGtK 2NUAwkCu6nM9pfrTxfP2m92DtnhcwzydkAC5LkWOtTTVz8jZKDkygcJpKIdXM2UQo9X/ Td+g== X-Forwarded-Encrypted: i=1; AJvYcCVOTcWcVbYCZ3XZlTO+9bzhNQQ4osE78BOAyK3xmQdEJ5/eqd1JyPn7wDzl7ryw01YoC/5CiQKrfBz5jnmN@postgresql.org X-Gm-Message-State: AOJu0YzSVMtzPxohqeTbZ+fcNYpYdo7Q7mq5DCi32ztZNPMtBm3Ti3or w4j8+V15Q+3YnLq5r1ESTuujO2QW/o+U8Z9yblJszzqX9JoMOL1KcoGMURF1K3DuWWRVf+qN9RG S/jtm5KIIjes1ZBX/AP3FHRne08SEV+o= X-Gm-Gg: AY/fxX64RkFcHVLHhC3A1ZutMHhKDBBZ3eiYvTBKkhZpnRteX9Qq+RpcKhx7mPERQl6 EUyZxa7Yfsr+tbYqbENSOuHuJbt3icpQ7ikaw529waxZynXaA3sxdlEjRcVAKJKZq9izhquQdDh t5+kFcYHFf3ak8FsCO5h/NExzmzK/bArwV7Oz36+Uyeyllytl36CHM45mrnE9UinxWTbBD3nKdX ykPKbeI/gkdhqsmsQ2IC7gltGDkbj9efPL1Woi+5WeIqZA9IzxXDNQIqbGwVXdDiMoZbg== X-Google-Smtp-Source: AGHT+IE23l0SJhu/k0DMPzSaHx8QmCte0ylfrElVzWqMEjKx41y+khAZAzEjxPKldQvRMu9tlf7YTrvuowDoNfUENzo= X-Received: by 2002:a17:907:3e84:b0:b84:206f:c0c5 with SMTP id a640c23a62f3a-b844517a062mr1174712466b.34.1768004198010; Fri, 09 Jan 2026 16:16:38 -0800 (PST) MIME-Version: 1.0 References: <07147023882ac6c4424df946fd4b82b8e8c211a5.camel@j-davis.com> <341357.1741201933@sss.pgh.pa.us> In-Reply-To: From: Sami Imseih Date: Fri, 9 Jan 2026 18:16:26 -0600 X-Gm-Features: AZwV_QgrF88BOipXRFZEhsjE3Cg8u-cpdZBH2Kz2FI98UkUzivtEM0JMwca3tn8 Message-ID: Subject: Re: explain plans for foreign servers To: dinesh salve Cc: Tom Lane , pgsql-hackers@postgresql.org, Jeff Davis Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > 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. After looking at this a bit more, I don't think the INSERT case is the only one. Here is an example: ``` -- Setup foreign server and table CREATE EXTENSION postgres_fdw; CREATE SERVER remote_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost', port '5432', dbname 'postgres'); CREATE USER MAPPING FOR CURRENT_USER SERVER remote_server OPTIONS (user 'postgres', password 'password'); CREATE TABLE local_table (id int, name text); CREATE FOREIGN TABLE remote_table ( id int, name text ) SERVER remote_server OPTIONS (table_name 'local_table'); postgres=# load 'postgres_fdw'; LOAD postgres=# explain (remote_plans, verbose) select * from remote_table where id = (select 1); ERROR: there is no parameter $1 CONTEXT: remote SQL command: EXPLAIN ( FORMAT TEXT, VERBOSE 1, COSTS 1, SETTINGS 0) SELECT id, name FROM public.local_table WHERE ((id = $1::integer)) postgres=# postgres=# explain (verbose) select * from remote_table where id = (select 1); QUERY PLAN ---------------------------------------------------------------------------------- Foreign Scan on public.remote_table (cost=100.01..128.54 rows=7 width=36) Output: remote_table.id, remote_table.name Remote SQL: SELECT id, name FROM public.local_table WHERE ((id = $1::integer)) InitPlan expr_1 -> Result (cost=0.00..0.01 rows=1 width=4) Output: 1 (6 rows) ```` The above is due to the value of the subquery is sent as a parameter; see `printRemoteParam`in deparse.c. Also see this comment in deparse.c: ``` * This is used when we're just trying to EXPLAIN the remote query. * We don't have the actual value of the runtime parameter yet, and we don't * want the remote planner to generate a plan that depends on such a value * anyway. Thus, we can't do something simple like "$1::paramtype". * Instead, we emit "((SELECT null::paramtype)::paramtype)". ``` The above comment is related to the EXPLAIN being sent remotely when use_remote_estimate is enabled. But the point is, it will not be possible to send the runtime parameters to the remote EXPLAIN. So "generic_plan" as a mandatory option may be the best way to proceed, and only make the remote_plans option available to remote versions that support this option. Maybe others have a better way? > 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 >= 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? I think if we try to forward an option that is on the source side but not on the remote side, it's fair to just error out with "ERROR: unrecognized EXPLAIN option..." That should be acceptable, because the user will know better not to use that option. right? -- Sami Imseih Amazon Web Services (AWS)