Consider a Result node's relids in ExplainPreScanNode.
authorRobert Haas <rhaas@postgresql.org>
Mon, 21 Apr 2025 17:35:28 +0000 (13:35 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 31 Jul 2025 15:39:40 +0000 (11:39 -0400)
Now that a Result node has a relids set, add the relids that it
carries the set accumulated by ExplainPreScanNode so that we
generate unique relation aliases for all of the referenced relations
when it calls select_rtable_names_for_explain. The effect of this
changes is that a few things get schema-qualified in the regression
test outputs that previously were not. In similar cases not involving
a Result node, we were already schema-qualifying, so this appears to
be an improvement.

XXX. I have broken this out as a separate commit for now; however,
it could be merged with the commit to add 'relids' to 'Result'; or
the patch series could even be rejiggered to present this as the
primary benefit of that change, leaving the EXPLAIN changes as a
secondary benefit, instead of the current organization, which does
the reverse.

src/backend/commands/explain.c
src/test/regress/expected/generated_virtual.out
src/test/regress/expected/join.out
src/test/regress/expected/partition_join.out

index 42723c3a1503cdb55127e83759a5048360a7f273..e8bd4c560dd32bd8ca4fa5601fb40654a5b033ca 100644 (file)
@@ -1230,6 +1230,10 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
                        *rels_used = bms_add_members(*rels_used,
                                                                                 ((MergeAppend *) plan)->apprelids);
                        break;
+               case T_Result:
+                       *rels_used = bms_add_members(*rels_used,
+                                                                                ((Result *) plan)->relids);
+                       break;
                default:
                        break;
        }
index 8b25e77bb4d4b58730eed1ca2ea575cf93dbab73..70727623bca977ed4fb85e0c67a486a0f8adbd69 100644 (file)
@@ -1570,15 +1570,15 @@ where coalesce(t2.b, 1) = 2 or t1.a is null;
 -- Ensure that the generation expressions are wrapped into PHVs if needed
 explain (verbose, costs off)
 select t2.* from gtest32 t1 left join gtest32 t2 on false;
-                      QUERY PLAN                      
-------------------------------------------------------
+                          QUERY PLAN                           
+---------------------------------------------------------------
  Nested Loop Left Join
-   Output: a, (a * 2), (20), (COALESCE(a, 100)), e
+   Output: t2.a, (t2.a * 2), (20), (COALESCE(t2.a, 100)), t2.e
    Join Filter: false
    ->  Seq Scan on generated_virtual_tests.gtest32 t1
          Output: t1.a, t1.b, t1.c, t1.d, t1.e
    ->  Result
-         Output: a, e, 20, COALESCE(a, 100)
+         Output: t2.a, t2.e, 20, COALESCE(t2.a, 100)
          One-Time Filter: false
          Replaces: Scan on t2
 (9 rows)
index acf4fe046014661f73f6385440286625a56d9749..8955481863a2d2fbc15b588abaea6d7aa015ac5a 100644 (file)
@@ -4133,9 +4133,9 @@ select * from t t1
                         QUERY PLAN                        
 ----------------------------------------------------------
  Nested Loop Left Join
-   Output: t1.i, (1), t2.i2, i3, t4.i4
+   Output: t1.i, (1), t2.i2, t3.i3, t4.i4
    ->  Nested Loop Left Join
-         Output: t1.i, t2.i2, (1), i3
+         Output: t1.i, t2.i2, (1), t3.i3
          Join Filter: false
          ->  Hash Left Join
                Output: t1.i, t2.i2, (1)
@@ -4148,8 +4148,9 @@ select * from t t1
                      ->  Seq Scan on pg_temp.t t2
                            Output: t2.i2, 1
          ->  Result
-               Output: i3
+               Output: t3.i3
                One-Time Filter: false
+               Replaces: Scan on t3
    ->  Memoize
          Output: t4.i4
          Cache Key: (1)
@@ -4157,7 +4158,7 @@ select * from t t1
          ->  Index Only Scan using t_pkey on pg_temp.t t4
                Output: t4.i4
                Index Cond: (t4.i4 > (1))
-(25 rows)
+(26 rows)
 
 explain (verbose, costs off)
 select * from
@@ -6050,7 +6051,7 @@ on t1.q1 = t2.q1;
                  QUERY PLAN                 
 --------------------------------------------
  Hash Left Join
-   Hash Cond: (t1.q1 = q1)
+   Hash Cond: (t1.q1 = t2.q1)
    ->  Seq Scan on int8_tbl t1
    ->  Hash
          ->  Result
@@ -6067,7 +6068,7 @@ on t1.q1 = t2.q1;
                  QUERY PLAN                 
 --------------------------------------------
  Hash Left Join
-   Hash Cond: (t1.q1 = q1)
+   Hash Cond: (t1.q1 = t2.q1)
    ->  Seq Scan on int8_tbl t1
    ->  Hash
          ->  Result
@@ -6397,13 +6398,13 @@ SELECT q2 FROM
                       QUERY PLAN                      
 ------------------------------------------------------
  Nested Loop Left Join
-   Output: q2
+   Output: int8_tbl.q2
    Join Filter: NULL::boolean
    Filter: (('constant'::text) >= ('constant'::text))
    ->  Seq Scan on public.int4_tbl
          Output: int4_tbl.f1
    ->  Result
-         Output: q2, 'constant'::text
+         Output: int8_tbl.q2, 'constant'::text
          One-Time Filter: false
          Replaces: Scan on int8_tbl
 (10 rows)
@@ -6756,7 +6757,7 @@ where q1.x = q2.y;
 --------------------------
  Result
    One-Time Filter: false
-   Replaces: Scan on sj_1
+   Replaces: Scan on sj
 (3 rows)
 
 -- We can't use a cross-EC generated self join qual because of current logic of
@@ -8746,15 +8747,15 @@ select * from int4_tbl t1,
 explain (verbose, costs off)
 select * from int8_tbl i8 left join lateral
   (select *, i8.q2 from int4_tbl where false) ss on true;
-              QUERY PLAN              
---------------------------------------
+                  QUERY PLAN                  
+----------------------------------------------
  Nested Loop Left Join
-   Output: i8.q1, i8.q2, f1, (i8.q2)
+   Output: i8.q1, i8.q2, int4_tbl.f1, (i8.q2)
    Join Filter: false
    ->  Seq Scan on public.int8_tbl i8
          Output: i8.q1, i8.q2
    ->  Result
-         Output: f1, i8.q2
+         Output: int4_tbl.f1, i8.q2
          One-Time Filter: false
          Replaces: Scan on int4_tbl
 (9 rows)
@@ -8762,14 +8763,14 @@ select * from int8_tbl i8 left join lateral
 explain (verbose, costs off)
 select * from int8_tbl i8 left join lateral
   (select *, i8.q2 from int4_tbl i1, int4_tbl i2 where false) ss on true;
-               QUERY PLAN                
------------------------------------------
+                  QUERY PLAN                   
+-----------------------------------------------
  Nested Loop Left Join
-   Output: i8.q1, i8.q2, f1, f1, (i8.q2)
+   Output: i8.q1, i8.q2, i1.f1, i2.f1, (i8.q2)
    ->  Seq Scan on public.int8_tbl i8
          Output: i8.q1, i8.q2
    ->  Result
-         Output: f1, f1, i8.q2
+         Output: i1.f1, i2.f1, i8.q2
          One-Time Filter: false
          Replaces: Join on i1, i2
 (8 rows)
index 52c4ffffd81de3aeb5dceb77d136da7629bd3796..966b2eb6eb93be29299f559d18f78e51125584b3 100644 (file)
@@ -1626,7 +1626,7 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1
                     QUERY PLAN                    
 --------------------------------------------------
  Hash Left Join
-   Hash Cond: (t2.b = a)
+   Hash Cond: (t2.b = prt1.a)
    ->  Append
          ->  Hash Join
                Hash Cond: (t3_1.a = t2_1.b)
@@ -1654,9 +1654,9 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1
                  QUERY PLAN                 
 --------------------------------------------
  Sort
-   Sort Key: a, t2.b
+   Sort Key: prt1.a, t2.b
    ->  Hash Left Join
-         Hash Cond: (t2.b = a)
+         Hash Cond: (t2.b = prt1.a)
          ->  Append
                ->  Seq Scan on prt2_p1 t2_1
                      Filter: (a = 0)
@@ -2242,10 +2242,10 @@ SELECT COUNT(*) FROM prt1_l t1 LEFT JOIN LATERAL
 -- join with one side empty
 EXPLAIN (COSTS OFF)
 SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c;
-                               QUERY PLAN                                
--------------------------------------------------------------------------
+                                          QUERY PLAN                                          
+----------------------------------------------------------------------------------------------
  Hash Left Join
-   Hash Cond: ((t2.b = a) AND (t2.a = b) AND ((t2.c)::text = (c)::text))
+   Hash Cond: ((t2.b = prt1_l.a) AND (t2.a = prt1_l.b) AND ((t2.c)::text = (prt1_l.c)::text))
    ->  Append
          ->  Seq Scan on prt2_l_p1 t2_1
          ->  Seq Scan on prt2_l_p2_p1 t2_2