@@ -268,8 +268,9 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
268268 case RTE_CTE :
269269
270270 /*
271- * CTEs don't support parameterized paths, so just go ahead
272- * and build their paths immediately.
271+ * CTEs don't support making a choice between parameterized
272+ * and unparameterized paths, so just go ahead and build their
273+ * paths immediately.
273274 */
274275 if (rte -> self_reference )
275276 set_worktable_pathlist (root , rel , rte );
@@ -376,8 +377,18 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
376377static void
377378set_plain_rel_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
378379{
380+ Relids required_outer ;
381+
382+ /*
383+ * We don't support pushing join clauses into the quals of a seqscan, but
384+ * it could still have required parameterization due to LATERAL refs in
385+ * its tlist. (That can only happen if the seqscan is on a relation
386+ * pulled up out of a UNION ALL appendrel.)
387+ */
388+ required_outer = rel -> lateral_relids ;
389+
379390 /* Consider sequential scan */
380- add_path (rel , create_seqscan_path (root , rel , NULL ));
391+ add_path (rel , create_seqscan_path (root , rel , required_outer ));
381392
382393 /* Consider index scans */
383394 create_index_paths (root , rel );
@@ -536,10 +547,10 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
536547 * CE failed, so finish copying/modifying targetlist and join quals.
537548 *
538549 * Note: the resulting childrel->reltargetlist may contain arbitrary
539- * expressions, which normally would not occur in a reltargetlist.
540- * That is okay because nothing outside of this routine will look at
541- * the child rel's reltargetlist . We do have to cope with the case
542- * while constructing attr_widths estimates below, though .
550+ * expressions, which otherwise would not occur in a reltargetlist.
551+ * Code that might be looking at an appendrel child must cope with
552+ * such . Note in particular that "arbitrary expression" can include
553+ * "Var belonging to another relation", due to LATERAL references .
543554 */
544555 childrel -> joininfo = (List * )
545556 adjust_appendrel_attrs (root ,
@@ -610,7 +621,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
610621 int pndx = parentvar -> varattno - rel -> min_attr ;
611622 int32 child_width = 0 ;
612623
613- if (IsA (childvar , Var ))
624+ if (IsA (childvar , Var ) &&
625+ ((Var * ) childvar )-> varno == childrel -> relid )
614626 {
615627 int cndx = ((Var * ) childvar )-> varattno - childrel -> min_attr ;
616628
@@ -1054,17 +1066,10 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
10541066
10551067 /*
10561068 * If it's a LATERAL subquery, it might contain some Vars of the current
1057- * query level, requiring it to be treated as parameterized.
1069+ * query level, requiring it to be treated as parameterized, even though
1070+ * we don't support pushing down join quals into subqueries.
10581071 */
1059- if (rte -> lateral )
1060- {
1061- required_outer = pull_varnos_of_level ((Node * ) subquery , 1 );
1062- /* Enforce convention that empty required_outer is exactly NULL */
1063- if (bms_is_empty (required_outer ))
1064- required_outer = NULL ;
1065- }
1066- else
1067- required_outer = NULL ;
1072+ required_outer = rel -> lateral_relids ;
10681073
10691074 /* We need a workspace for keeping track of set-op type coercions */
10701075 differentTypes = (bool * )
@@ -1175,29 +1180,18 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
11751180/*
11761181 * set_function_pathlist
11771182 * Build the (single) access path for a function RTE
1178- *
1179- * As with subqueries, a function RTE's path might be parameterized due to
1180- * LATERAL references, but that's inherent in the function expression and
1181- * not a result of pushing down join quals.
11821183 */
11831184static void
11841185set_function_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
11851186{
11861187 Relids required_outer ;
11871188
11881189 /*
1189- * If it's a LATERAL function, it might contain some Vars of the current
1190- * query level, requiring it to be treated as parameterized.
1190+ * We don't support pushing join clauses into the quals of a function
1191+ * scan, but it could still have required parameterization due to LATERAL
1192+ * refs in the function expression.
11911193 */
1192- if (rte -> lateral )
1193- {
1194- required_outer = pull_varnos_of_level (rte -> funcexpr , 0 );
1195- /* Enforce convention that empty required_outer is exactly NULL */
1196- if (bms_is_empty (required_outer ))
1197- required_outer = NULL ;
1198- }
1199- else
1200- required_outer = NULL ;
1194+ required_outer = rel -> lateral_relids ;
12011195
12021196 /* Generate appropriate path */
12031197 add_path (rel , create_functionscan_path (root , rel , required_outer ));
@@ -1209,29 +1203,18 @@ set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
12091203/*
12101204 * set_values_pathlist
12111205 * Build the (single) access path for a VALUES RTE
1212- *
1213- * As with subqueries, a VALUES RTE's path might be parameterized due to
1214- * LATERAL references, but that's inherent in the values expressions and
1215- * not a result of pushing down join quals.
12161206 */
12171207static void
12181208set_values_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
12191209{
12201210 Relids required_outer ;
12211211
12221212 /*
1223- * If it's a LATERAL RTE, it might contain some Vars of the current query
1224- * level, requiring it to be treated as parameterized.
1213+ * We don't support pushing join clauses into the quals of a values scan,
1214+ * but it could still have required parameterization due to LATERAL refs
1215+ * in the values expressions.
12251216 */
1226- if (rte -> lateral )
1227- {
1228- required_outer = pull_varnos_of_level ((Node * ) rte -> values_lists , 0 );
1229- /* Enforce convention that empty required_outer is exactly NULL */
1230- if (bms_is_empty (required_outer ))
1231- required_outer = NULL ;
1232- }
1233- else
1234- required_outer = NULL ;
1217+ required_outer = rel -> lateral_relids ;
12351218
12361219 /* Generate appropriate path */
12371220 add_path (rel , create_valuesscan_path (root , rel , required_outer ));
@@ -1245,7 +1228,7 @@ set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
12451228 * Build the (single) access path for a non-self-reference CTE RTE
12461229 *
12471230 * There's no need for a separate set_cte_size phase, since we don't
1248- * support parameterized paths for CTEs.
1231+ * support join-qual- parameterized paths for CTEs.
12491232 */
12501233static void
12511234set_cte_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
@@ -1256,6 +1239,7 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
12561239 int ndx ;
12571240 ListCell * lc ;
12581241 int plan_id ;
1242+ Relids required_outer ;
12591243
12601244 /*
12611245 * Find the referenced CTE, and locate the plan previously made for it.
@@ -1294,8 +1278,16 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
12941278 /* Mark rel with estimated output rows, width, etc */
12951279 set_cte_size_estimates (root , rel , cteplan );
12961280
1281+ /*
1282+ * We don't support pushing join clauses into the quals of a CTE scan, but
1283+ * it could still have required parameterization due to LATERAL refs in
1284+ * its tlist. (That can only happen if the CTE scan is on a relation
1285+ * pulled up out of a UNION ALL appendrel.)
1286+ */
1287+ required_outer = rel -> lateral_relids ;
1288+
12971289 /* Generate appropriate path */
1298- add_path (rel , create_ctescan_path (root , rel ));
1290+ add_path (rel , create_ctescan_path (root , rel , required_outer ));
12991291
13001292 /* Select cheapest path (pretty easy in this case...) */
13011293 set_cheapest (rel );
@@ -1306,14 +1298,15 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
13061298 * Build the (single) access path for a self-reference CTE RTE
13071299 *
13081300 * There's no need for a separate set_worktable_size phase, since we don't
1309- * support parameterized paths for CTEs.
1301+ * support join-qual- parameterized paths for CTEs.
13101302 */
13111303static void
13121304set_worktable_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
13131305{
13141306 Plan * cteplan ;
13151307 PlannerInfo * cteroot ;
13161308 Index levelsup ;
1309+ Relids required_outer ;
13171310
13181311 /*
13191312 * We need to find the non-recursive term's plan, which is in the plan
@@ -1338,8 +1331,18 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
13381331 /* Mark rel with estimated output rows, width, etc */
13391332 set_cte_size_estimates (root , rel , cteplan );
13401333
1334+ /*
1335+ * We don't support pushing join clauses into the quals of a worktable
1336+ * scan, but it could still have required parameterization due to LATERAL
1337+ * refs in its tlist. (That can only happen if the worktable scan is on a
1338+ * relation pulled up out of a UNION ALL appendrel. I'm not sure this is
1339+ * actually possible given the restrictions on recursive references, but
1340+ * it's easy enough to support.)
1341+ */
1342+ required_outer = rel -> lateral_relids ;
1343+
13411344 /* Generate appropriate path */
1342- add_path (rel , create_worktablescan_path (root , rel ));
1345+ add_path (rel , create_worktablescan_path (root , rel , required_outer ));
13431346
13441347 /* Select cheapest path (pretty easy in this case...) */
13451348 set_cheapest (rel );
0 commit comments