]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix setrefs.c's failure to do expression processing on prune steps.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Jan 2025 01:40:07 +0000 (20:40 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Jan 2025 01:40:07 +0000 (20:40 -0500)
We should run the expression subtrees of PartitionedRelPruneInfo
structs through fix_scan_expr.  Failure to do so means that
AlternativeSubPlans within those expressions won't be cleaned up
properly, resulting in "unrecognized node type" errors since v14.

It seems fairly likely that at least some of the other steps done
by fix_scan_expr are important here as well, resulting in as-yet-
undetected bugs.  Therefore, I've chosen to back-patch this to
all supported branches including v13, even though the known
symptom doesn't manifest in v13.

Per bug #18778 from Alexander Lakhin.

Discussion: https://postgr.es/m/18778-24cd399df6c806af@postgresql.org

src/backend/optimizer/plan/setrefs.c
src/test/regress/expected/partition_prune.out
src/test/regress/sql/partition_prune.sql

index f66de15db3188282ec3690fadffe1014ea9963e6..e57864557047ac653f09738aa122ddeaa5881b0a 100644 (file)
@@ -1405,6 +1405,12 @@ set_append_references(PlannerInfo *root,
                                PartitionedRelPruneInfo *pinfo = lfirst(l2);
 
                                pinfo->rtindex += rtoffset;
+                               pinfo->initial_pruning_steps =
+                                       fix_scan_list(root, pinfo->initial_pruning_steps,
+                                                                 rtoffset);
+                               pinfo->exec_pruning_steps =
+                                       fix_scan_list(root, pinfo->exec_pruning_steps,
+                                                                 rtoffset);
                        }
                }
        }
@@ -1477,6 +1483,12 @@ set_mergeappend_references(PlannerInfo *root,
                                PartitionedRelPruneInfo *pinfo = lfirst(l2);
 
                                pinfo->rtindex += rtoffset;
+                               pinfo->initial_pruning_steps =
+                                       fix_scan_list(root, pinfo->initial_pruning_steps,
+                                                                 rtoffset);
+                               pinfo->exec_pruning_steps =
+                                       fix_scan_list(root, pinfo->exec_pruning_steps,
+                                                                 rtoffset);
                        }
                }
        }
index 6e80947d8745492c9a40bb2b5aa909e2b08f24f3..1f31dd4cf24e98729a2eff189c3c27427d911438 100644 (file)
@@ -1839,6 +1839,38 @@ explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
 (2 rows)
 
 drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, iboolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
+-- check that AlternativeSubPlan within a pruning expression gets cleaned up
+create table asptab (id int primary key) partition by range (id);
+create table asptab0 partition of asptab for values from (0) to (1);
+create table asptab1 partition of asptab for values from (1) to (2);
+explain (costs off)
+select * from
+  (select exists (select 1 from int4_tbl tinner where f1 = touter.f1) as b
+   from int4_tbl touter) ss,
+  asptab
+where asptab.id > ss.b::int;
+                                        QUERY PLAN                                         
+-------------------------------------------------------------------------------------------
+ Nested Loop
+   ->  Seq Scan on int4_tbl touter
+   ->  Append
+         ->  Index Only Scan using asptab0_pkey on asptab0 asptab_1
+               Index Cond: (id > ((alternatives: SubPlan 3 or hashed SubPlan 4))::integer)
+               SubPlan 3
+                 ->  Seq Scan on int4_tbl tinner_2
+                       Filter: (f1 = touter.f1)
+               SubPlan 4
+                 ->  Seq Scan on int4_tbl tinner_3
+         ->  Index Only Scan using asptab1_pkey on asptab1 asptab_2
+               Index Cond: (id > ((alternatives: SubPlan 3 or hashed SubPlan 4))::integer)
+   SubPlan 1
+     ->  Seq Scan on int4_tbl tinner
+           Filter: (f1 = touter.f1)
+   SubPlan 2
+     ->  Seq Scan on int4_tbl tinner_1
+(17 rows)
+
+drop table asptab;
 --
 -- Test Partition pruning for HASH partitioning
 --
index fec07a9a30b444105a352fdd062cdde268b11e3a..d9e0fafbfb25e30b1b6a049a261765831ee42b19 100644 (file)
@@ -362,6 +362,21 @@ explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
 
 drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, iboolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
 
+-- check that AlternativeSubPlan within a pruning expression gets cleaned up
+
+create table asptab (id int primary key) partition by range (id);
+create table asptab0 partition of asptab for values from (0) to (1);
+create table asptab1 partition of asptab for values from (1) to (2);
+
+explain (costs off)
+select * from
+  (select exists (select 1 from int4_tbl tinner where f1 = touter.f1) as b
+   from int4_tbl touter) ss,
+  asptab
+where asptab.id > ss.b::int;
+
+drop table asptab;
+
 --
 -- Test Partition pruning for HASH partitioning
 --