|
417 | 417 | create_lateral_join_info(PlannerInfo *root)
|
418 | 418 | {
|
419 | 419 | bool found_laterals = false;
|
| 420 | + Relids prev_parents PG_USED_FOR_ASSERTS_ONLY = NULL; |
420 | 421 | Index rti;
|
421 | 422 | ListCell *lc;
|
422 | 423 |
|
@@ -625,33 +626,43 @@ create_lateral_join_info(PlannerInfo *root)
|
625 | 626 | * every child anyway, and there's no value in forcing extra
|
626 | 627 | * reparameterize_path() calls. Similarly, a lateral reference to the
|
627 | 628 | * parent prevents use of otherwise-movable join rels for each child.
|
| 629 | + * |
| 630 | + * It's possible for child rels to have their own children, in which case |
| 631 | + * the topmost parent's lateral info must be propagated all the way down. |
| 632 | + * This code handles that case correctly so long as append_rel_list has |
| 633 | + * entries for child relationships before grandchild relationships, which |
| 634 | + * is an okay assumption right now, but we'll need to be careful to |
| 635 | + * preserve it. The assertions below check for incorrect ordering. |
628 | 636 | */
|
629 |
| - for (rti = 1; rti < root->simple_rel_array_size; rti++) |
| 637 | + foreach(lc, root->append_rel_list) |
630 | 638 | {
|
631 |
| - RelOptInfo *brel = root->simple_rel_array[rti]; |
| 639 | + AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc); |
| 640 | + RelOptInfo *parentrel = root->simple_rel_array[appinfo->parent_relid]; |
| 641 | + RelOptInfo *childrel = root->simple_rel_array[appinfo->child_relid]; |
632 | 642 |
|
633 |
| - if (brel == NULL || brel->reloptkind != RELOPT_BASEREL) |
| 643 | + /* |
| 644 | + * If we're processing a subquery of a query with inherited target rel |
| 645 | + * (cf. inheritance_planner), append_rel_list may contain entries for |
| 646 | + * tables that are not part of the current subquery and hence have no |
| 647 | + * RelOptInfo. Ignore them. We can ignore dead rels, too. |
| 648 | + */ |
| 649 | + if (parentrel == NULL || !IS_SIMPLE_REL(parentrel)) |
634 | 650 | continue;
|
635 | 651 |
|
636 |
| - if (root->simple_rte_array[rti]->inh) |
637 |
| - { |
638 |
| - foreach(lc, root->append_rel_list) |
639 |
| - { |
640 |
| - AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc); |
641 |
| - RelOptInfo *childrel; |
642 |
| - |
643 |
| - if (appinfo->parent_relid != rti) |
644 |
| - continue; |
645 |
| - childrel = root->simple_rel_array[appinfo->child_relid]; |
646 |
| - Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL); |
647 |
| - Assert(childrel->direct_lateral_relids == NULL); |
648 |
| - childrel->direct_lateral_relids = brel->direct_lateral_relids; |
649 |
| - Assert(childrel->lateral_relids == NULL); |
650 |
| - childrel->lateral_relids = brel->lateral_relids; |
651 |
| - Assert(childrel->lateral_referencers == NULL); |
652 |
| - childrel->lateral_referencers = brel->lateral_referencers; |
653 |
| - } |
654 |
| - } |
| 652 | + /* Verify that children are processed before grandchildren */ |
| 653 | +#ifdef USE_ASSERT_CHECKING |
| 654 | + prev_parents = bms_add_member(prev_parents, appinfo->parent_relid); |
| 655 | + Assert(!bms_is_member(appinfo->child_relid, prev_parents)); |
| 656 | +#endif |
| 657 | + |
| 658 | + /* OK, propagate info down */ |
| 659 | + Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL); |
| 660 | + Assert(childrel->direct_lateral_relids == NULL); |
| 661 | + childrel->direct_lateral_relids = parentrel->direct_lateral_relids; |
| 662 | + Assert(childrel->lateral_relids == NULL); |
| 663 | + childrel->lateral_relids = parentrel->lateral_relids; |
| 664 | + Assert(childrel->lateral_referencers == NULL); |
| 665 | + childrel->lateral_referencers = parentrel->lateral_referencers; |
655 | 666 | }
|
656 | 667 | }
|
657 | 668 |
|
|
0 commit comments