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 1x2Qei-005lUQ-2t for pgsql-bugs@arkaria.postgresql.org; Fri, 04 Sep 2026 09:56:20 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x2Qeg-005zt2-2i for pgsql-bugs@arkaria.postgresql.org; Fri, 04 Sep 2026 09:56:18 +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 1x2Ncy-0050Q0-38 for pgsql-bugs@lists.postgresql.org; Fri, 04 Sep 2026 06:42:21 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x2Ncq-00000002rS8-0SaF for pgsql-bugs@lists.postgresql.org; Fri, 04 Sep 2026 06:42:20 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=IVFEy5WNXhmrIr0UFwn7SOhrzdrbBfj1ogrUN1lvqXY=; b=rX25ATC8M320JKvQA06UpfSoN2 tPFR6qMC4zoZoHkyZqrEDD9EObbq2P1gpn1H7CV763mbeZlT0wvZuiJ8pOLBaMJlyWR8EnBb+rZNF Tv9nTBBwzx9VCTm8igDS0JwWuSTNDYwHn6sJjlLB7eU+Y1oY6lwFM0d95Fcq0Pxntk7IRZ15GxPel qxY9H5IJaRabk2B3br5ePeLFgYae5ppfrlh8iwPlTJMm/J7JbiNdujmNyB06FR8IDutIXnHG56jPj TcrqDmVzmtTZYVVRQCLaVy/46HMHwxBzex2/p1z6qNApunQwSmiXgqcO4gkMwzBXj8VwbPEdEvsi9 j6609oQQ==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x2Ncj-00BsV6-0Z for pgsql-bugs@lists.postgresql.org; Fri, 04 Sep 2026 06:42:10 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x2Nch-0000000EIM6-2vIp for pgsql-bugs@lists.postgresql.org; Fri, 04 Sep 2026 06:42:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19653: "variable not found in subplan target list" during planning with parallel parameterized nested loop, To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: 10215501441@stu.ecnu.edu.cn Reply-To: 10215501441@stu.ecnu.edu.cn, pgsql-bugs@lists.postgresql.org Date: Fri, 04 Sep 2026 06:41:33 +0000 Message-ID: <19653-9352cc6ba17b662f@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19653 Logged by: Annie Email address: 10215501441@stu.ecnu.edu.cn PostgreSQL version: 18.6 Operating system: Ubuntu 20.04.6 LTS (Focal Fossa)=EF=BC=8Cx86_64 Description: =20 ## Description A query using a partitioned left/right join split, with `enable_partitionwise_join`, parallel settings, and `GROUP BY ROLLUP` fails at planning time with: ``` ERROR: variable not found in subplan target list ``` The same query against a single non=E2=80=91partitioned table works correct= ly. The error occurs during plan construction, not execution. The problem arises when all of the following are true: 1. The right table of a join has **no statistics** (only left table is analyzed), causing the planner to choose a **parameterized nested loop**. 2. **Parallel query** is enabled with very low cost parameters, leading to a `Gather` node. 3. `GROUP BY ROLLUP` produces a **MixedAggregate** node that trims the child targetlist to only required columns. 4. The inner index scan of the nested loop has a filter that references both outer and inner columns (e.g., `m_l.tsvec @@ tsq`), but the inner subplan targetlist no longer contains the outer column after trimming. ## How to reproduce ```sql -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Database setup =3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D DROP DATABASE IF EXISTS repro_postgres810_db3_min; CREATE DATABASE repro_postgres810_db3_min; \c repro_postgres810_db3_min; -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Session parameters =3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D SET enable_partitionwise_join =3D on; SET enable_partition_pruning =3D on; SET enable_partitionwise_aggregate =3D on; SET enable_parallel_append =3D on; SET enable_parallel_hash =3D on; SET max_parallel_workers_per_gather =3D 2; SET min_parallel_table_scan_size =3D 0; SET parallel_setup_cost =3D 0; SET parallel_tuple_cost =3D 0; -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Single source table =3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D CREATE TABLE m_src(rowid bigint PRIMARY KEY, tsvec tsvector, tsq tsquery); INSERT INTO m_src VALUES (1, to_tsvector('english','quick brown fox'), to_tsquery('english','alpha & beta')), (2, to_tsvector('english','quick brown fox'), to_tsquery('english','alpha & beta')), (3, to_tsvector('english','quick brown fox'), to_tsquery('english','alpha & beta')); -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Left/right partitioned tables =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D CREATE TABLE m_l(rowid bigint PRIMARY KEY, tsvec tsvector) PARTITION BY RANGE (rowid); CREATE TABLE m_l_p1 PARTITION OF m_l FOR VALUES FROM (1) TO (10); INSERT INTO m_l SELECT rowid, tsvec FROM m_src; CREATE TABLE m_r(rowid bigint PRIMARY KEY, tsq tsquery) PARTITION BY RANGE (rowid); CREATE TABLE m_r_p1 PARTITION OF m_r FOR VALUES FROM (1) TO (10); INSERT INTO m_r SELECT rowid, tsq FROM m_src; -- Only analyze left table; right table has no statistics ANALYZE m_l; -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =E2=91=A0 Single=E2=80=91table quer= y (works) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D SELECT ARRAY['', '']::TEXT[] FROM m_src WHERE NOT (m_src.tsvec @@ m_src.tsq) GROUP BY ROLLUP (ARRAY['', '']::TEXT[]); -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =E2=91=A1 Multi=E2=80=91table query= (fails) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D SELECT ALL ARRAY['', '']::TEXT[] FROM ( SELECT COALESCE(m_l.rowid, m_r.rowid) AS rowid, m_l.tsvec AS tsvec, m_r.tsq AS tsq FROM m_l JOIN m_r ON m_l.rowid =3D m_r.rowid ) s WHERE NOT (s.tsvec @@ s.tsq) GROUP BY ROLLUP (ARRAY['', '']::TEXT[]); ``` ## Expected behavior The multi=E2=80=91table query should return the same result as the single= =E2=80=91table query: two rows (`""` and `{"",""}`), without any error. ## Actual behavior The query fails with: ``` ERROR: variable not found in subplan target list ``` This error is raised during planning (in the `setrefs.c` phase), not during execution. ## Additional notes The plan shape for the failing query is roughly: ``` MixedAggregate -> Gather -> Nested Loop -> Parallel Seq Scan on m_l_p1 -> Index Scan on m_r_p1 Index Cond: (rowid =3D m_l.rowid) Filter: (m_l.tsvec @@ tsq) ``` After `MixedAggregate` trims the targetlist, the inner index scan still references `m_l.tsvec` (an outer variable passed as a parameter), but it is no longer present in the subplan targetlist, leading to the error.