@@ -268,8 +268,9 @@ set_rel_size(PlannerInfo *root, RelOptInfo *rel,
268268case 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 */
274275if (rte -> self_reference )
275276set_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 */
383394create_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, whichnormally 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, whichotherwise 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 */
544555childrel -> joininfo = (List * )
545556adjust_appendrel_attrs (root ,
@@ -610,7 +621,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
610621int pndx = parentvar -> varattno - rel -> min_attr ;
611622int32 child_width = 0 ;
612623
613- if (IsA (childvar ,Var ))
624+ if (IsA (childvar ,Var )&&
625+ ((Var * )childvar )-> varno == childrel -> relid )
614626{
615627int 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 */
10701075differentTypes = (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{
11861187Relids 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 */
12031197add_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{
12201210Relids 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 */
12371220add_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+ * supportjoin-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)
12561239int ndx ;
12571240ListCell * lc ;
12581241int 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 */
12951279set_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...) */
13011293set_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+ * supportjoin-qual- parameterized paths for CTEs.
13101302 */
13111303static void
13121304set_worktable_pathlist (PlannerInfo * root ,RelOptInfo * rel ,RangeTblEntry * rte )
13131305{
13141306Plan * cteplan ;
13151307PlannerInfo * cteroot ;
13161308Index 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 */
13391332set_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...) */
13451348set_cheapest (rel );