1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-11 10:01:57 +03:00

Fix up planner infrastructure to support LATERAL properly.

This patch takes care of a number of problems having to do with failure
to choose valid join orders and incorrect handling of lateral references
pulled up from subqueries.  Notable changes:

* Add a LateralJoinInfo data structure similar to SpecialJoinInfo, to
represent join ordering constraints created by lateral references.
(I first considered extending the SpecialJoinInfo structure, but the
semantics are different enough that a separate data structure seems
better.)  Extend join_is_legal() and related functions to prevent trying
to form unworkable joins, and to ensure that we will consider joins that
satisfy lateral references even if the joins would be clauseless.

* Fill in the infrastructure needed for the last few types of relation scan
paths to support parameterization.  We'd have wanted this eventually
anyway, but it is necessary now because a relation that gets pulled up out
of a UNION ALL subquery may acquire a reltargetlist containing lateral
references, meaning that its paths *have* to be parameterized whether or
not we have any code that can push join quals down into the scan.

* Compute data about lateral references early in query_planner(), and save
in RelOptInfo nodes, to avoid repetitive calculations later.

* Assorted corner-case bug fixes.

There's probably still some bugs left, but this is a lot closer to being
real than it was before.
This commit is contained in:
Tom Lane
2012-08-26 22:48:55 -04:00
parent de87d47044
commit 9ff79b9d4e
30 changed files with 818 additions and 183 deletions

View File

@ -298,8 +298,19 @@ create_scan_plan(PlannerInfo *root, Path *best_path)
}
}
else
{
tlist = build_relation_tlist(rel);
/*
* If it's a parameterized otherrel, there might be lateral references
* in the tlist, which need to be replaced with Params. This cannot
* happen for regular baserels, though. Note use_physical_tlist()
* always fails for otherrels, so we don't need to check this above.
*/
if (rel->reloptkind != RELOPT_BASEREL && best_path->param_info)
tlist = (List *) replace_nestloop_params(root, (Node *) tlist);
}
/*
* Extract the relevant restriction clauses from the parent relation. The
* executor must apply all these restrictions during the scan, except for
@ -1583,6 +1594,7 @@ create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
{
TidScan *scan_plan;
Index scan_relid = best_path->path.parent->relid;
List *tidquals = best_path->tidquals;
List *ortidquals;
/* it should be a base rel... */
@ -1595,11 +1607,20 @@ create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses(scan_clauses, false);
/* Replace any outer-relation variables with nestloop params */
if (best_path->path.param_info)
{
tidquals = (List *)
replace_nestloop_params(root, (Node *) tidquals);
scan_clauses = (List *)
replace_nestloop_params(root, (Node *) scan_clauses);
}
/*
* Remove any clauses that are TID quals. This is a bit tricky since the
* tidquals list has implicit OR semantics.
*/
ortidquals = best_path->tidquals;
ortidquals = tidquals;
if (list_length(ortidquals) > 1)
ortidquals = list_make1(make_orclause(ortidquals));
scan_clauses = list_difference(scan_clauses, ortidquals);
@ -1607,7 +1628,7 @@ create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
scan_plan = make_tidscan(tlist,
scan_clauses,
scan_relid,
best_path->tidquals);
tidquals);
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
@ -1823,6 +1844,13 @@ create_ctescan_plan(PlannerInfo *root, Path *best_path,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses(scan_clauses, false);
/* Replace any outer-relation variables with nestloop params */
if (best_path->param_info)
{
scan_clauses = (List *)
replace_nestloop_params(root, (Node *) scan_clauses);
}
scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
plan_id, cte_param_id);
@ -1876,6 +1904,13 @@ create_worktablescan_plan(PlannerInfo *root, Path *best_path,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses(scan_clauses, false);
/* Replace any outer-relation variables with nestloop params */
if (best_path->param_info)
{
scan_clauses = (List *)
replace_nestloop_params(root, (Node *) scan_clauses);
}
scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
cteroot->wt_param_id);