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 1vOQli-007IIh-2B for pgsql-bugs@arkaria.postgresql.org; Thu, 27 Nov 2025 01:25:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vOQlh-002Yzt-0s for pgsql-bugs@arkaria.postgresql.org; Thu, 27 Nov 2025 01:25:57 +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 1vOQlg-002Yzk-3A for pgsql-bugs@lists.postgresql.org; Thu, 27 Nov 2025 01:25:57 +0000 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vOQlf-001hSI-0M for pgsql-bugs@lists.postgresql.org; Thu, 27 Nov 2025 01:25:57 +0000 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-343dfb673a8so326747a91.0 for ; Wed, 26 Nov 2025 17:25:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764206752; x=1764811552; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=O1iRyudGDnYAHvrO2YIHTKe1BFAEJdhnqhnj/7Ayp4E=; b=JjuTG86KgZu/N9paJn6tWRQdQi1cQAEzcVDeA0MpE4ike2zqtFJwiw0qdgY/65tthu sL4zF4ONmSuEYTKpnAxp7cSsNLVX5f4SAx6TkJdU7yGU3J49PZB+RRbVYiLn8TvIjI9A CT7MpdGTtBVhWxN3ku9A8oaWrrdoaPShQPrjlnCUifPLbhgrL8cl/AiAd378ZxJMtQaS mQIgpyTqcwTM5Jbk2j/Z5TJoP53XA/6SHW6kWcoo7d0w2yC+mdkqSZUjRrwnj/m8q4ol qE7ZWqlbv5iiSRaPQnNIe3P13touufguRx5XosXKWyfvZx7wDaeCT3xjC6ONosJjL8Gw T8iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764206752; x=1764811552; h=content-transfer-encoding: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=O1iRyudGDnYAHvrO2YIHTKe1BFAEJdhnqhnj/7Ayp4E=; b=oKR6aZbPOxEsn4XGt6N9jHGweAeDOeOeI8ChjRZDmVDvfnsDuVu5zmhJXGkYU08EJM 93JOd4QbNrsXSKDrNqTnLTQ+ga2JZRNk1Yb8zdXGikDVvv5vZNXaUcFikMtnXmmsDfnw zuPLQOYsnEf+Ps0nMruxLIIG5UW5xWEkKdl/BYN3JnGMFSlX/V9mkUolAdhJrMojqm/o GPP7jKLT+l0aRFfF+K1uWPXfuVyAXWFzRuGhDuocM1CbnEmEZkx8w4BbhDsasmyl0Rez WK4heFlwd+Rsj10IY6/DmVM8SFGxGQc2xPCbxueZnOQ0Ef255VuWQr8PBSF7yAAHaNet COmA== X-Forwarded-Encrypted: i=1; AJvYcCU17OZ2fy+a2J/zR64Q/oNu/JfBbUaFJ2Pn0XJmHIRAn5Z1xLAQspdd0cdvwxz/uzzPc0w7z3JwQdhN@lists.postgresql.org X-Gm-Message-State: AOJu0YwMWg2ex0x8KGx6muDCnyxPKbZO72bhpAwQoU3AgrdoKPgEPJEe UybqEuHMaWPfL0Ak8YBE0cNrpR8/+YU87+oEoQN4jmVFgeIs8goB0EmUi/8rhqbzHcejpS8v0YA aHe6HvJptool0OLdTETx8n3kFtQTIzgk= X-Gm-Gg: ASbGnctbzPfserzM4oyzVpSWJzWXRC4D0FiQgYxt0KqeToSoYZUSWUaUFVAqmWLw1Pl h711xTM32bWGkLg96wKhs4l+liG1tJ/NlvrUcRuR49sN+ZrGRrwXBIVj48iWI2Bp9bHjiIlUi3V 6NLJQ9/J+Ow7UjYPZ0RILjyKwhlIRfXFWcwdZJFbK5PZoYvY3R8ukdK3oo7MplJVVA9k3TmK2sD hbkIQqK6EhCgdQsenbBiSYVD78URN+dnkQPXggY7ZknDFl1vZ9Q0qNtnzZTgqEbTpdXoVoziKTe KDMN6bE= X-Google-Smtp-Source: AGHT+IFM12IYWYFGkxFJATNLYckmfoSIYoRZfJgbKoDsvNydSZroc6xhAExE8D3UtmplxFLXmFjR4TQe5VLX2hJJH08= X-Received: by 2002:a17:90b:1fc5:b0:32b:9750:10e4 with SMTP id 98e67ed59e1d1-34733f3eb71mr22248612a91.27.1764206752486; Wed, 26 Nov 2025 17:25:52 -0800 (PST) MIME-Version: 1.0 References: <19099-e05dcfa022fe553d@postgresql.org> <2960545.1761800903@sss.pgh.pa.us> <3017911.1761832112@sss.pgh.pa.us> In-Reply-To: From: Amit Langote Date: Thu, 27 Nov 2025 10:25:36 +0900 X-Gm-Features: AWmQ_bkkilBY3UMjTTxYPu_JfKWcL73o82DZIIl09p4u29OuuiFcycR85edJ-nA Message-ID: Subject: Re: BUG #19099: Conditional DELETE from partitioned table with non-updatable partition raises internal error To: David Rowley Cc: Tom Lane , Kirill Reshke , Tender Wang , jian he , exclusion@gmail.com, pgsql-bugs@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, Nov 26, 2025 at 8:27=E2=80=AFPM Amit Langote wrote: > On Thu, Nov 6, 2025 at 7:00=E2=80=AFPM Amit Langote wrote: > > Among those options, I considered the following block, which adds a > > ctid for the partitioned root table when it=E2=80=99s the only target i= n the > > query after partition pruning removes all child tables due to the > > WHERE false condition in the problematic case: > > > > /* > > * Ordinarily, we expect that leaf result relation(s) will have add= ed some > > * ROWID_VAR Vars to the query. However, it's possible that constr= aint > > * exclusion suppressed every leaf relation. The executor will get= upset > > * if the plan has no row identity columns at all, even though it w= ill > > * certainly process no rows. Handle this edge case by re-opening = the top > > * result relation and adding the row identity columns it would hav= e used, > > * as preprocess_targetlist() would have done if it weren't marked = "inh". > > * Then re-run build_base_rel_tlists() to ensure that the added col= umns > > * get propagated to the relation's reltarget. (This is a bit ugly= , but > > * it seems better to confine the ugliness and extra cycles to this > > * unusual corner case.) > > */ > > if (root->row_identity_vars =3D=3D NIL) > > { > > Relation target_relation; > > > > target_relation =3D table_open(target_rte->relid, NoLock); > > add_row_identity_columns(root, result_relation, > > target_rte, target_relation); > > table_close(target_relation, NoLock); > > build_base_rel_tlists(root, root->processed_tlist); > > /* There are no ROWID_VAR Vars in this case, so we're done. */ > > return; > > } > > > > If enable_partition_pruning is off, root->row_identity_vars already > > contains a RowIdentityVarInfo entry for the tableoid Var that was > > added while processing the foreign-table child partition. Because of > > that, the if (root->row_identity_vars =3D=3D NIL) block doesn=E2=80=99t= run in > > this case, so it won=E2=80=99t add any row identity columns such as cti= d for > > the partitioned root table. > > > > In theory, we could prevent the planner from adding tableoid in the > > first place when the child table doesn=E2=80=99t support any row identi= ty > > column -- or worse, doesn=E2=80=99t support the UPDATE/DELETE/MERGE com= mand at > > all -- but doing so would require changing the order in which tableoid > > appears in root->processed_tlist. That would be too invasive for a > > back-patch. > > I=E2=80=99ve implemented this alternative as well -- the version that pre= vents > adding tableoid when no other row-identity columns are added for the > child. That allows to keep root->row_identity_vars empty so the > dummy-root path can add ctid as intended by the above code block of > distribute_row_identity_vars(). > > This provides an alternative approach to compare against the other patch. Forgot to mention that with this approach, unlike the other patch, the targetlists are identical whether or not enable_partition_pruning is on, since in both cases the if (root->row_identity_vars =3D=3D NIL) block of distribute_row_identity_vars() executes: +SET enable_partition_pruning TO off; +EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM pt WHERE false; + QUERY PLAN +-------------------------------- + Delete on public.pt + -> Result + Output: pt.ctid + Replaces: Scan on pt + One-Time Filter: false +(5 rows) +SET enable_partition_pruning TO on; +EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM pt WHERE false; + QUERY PLAN +-------------------------------- + Delete on public.pt + -> Result + Output: ctid + Replaces: Scan on pt + One-Time Filter: false +(5 rows) pt.ctid in the off case vs only ctid in the on case has to do, I think, with there being more than one entry in the rtable in the pruning off case. --=20 Thanks, Amit Langote