@@ -765,6 +765,8 @@ inheritance_planner(PlannerInfo *root)
765
765
{
766
766
Query * parse = root -> parse ;
767
767
int parentRTindex = parse -> resultRelation ;
768
+ Bitmapset * subqueryRTindexes ;
769
+ Bitmapset * modifiableARIindexes ;
768
770
List * final_rtable = NIL ;
769
771
int save_rel_array_size = 0 ;
770
772
RelOptInfo * * save_rel_array = NULL ;
@@ -773,6 +775,7 @@ inheritance_planner(PlannerInfo *root)
773
775
List * returningLists = NIL ;
774
776
List * rowMarks ;
775
777
ListCell * lc ;
778
+ Index rti ;
776
779
777
780
/*
778
781
* We generate a modified instance of the original Query for each target
@@ -788,13 +791,54 @@ inheritance_planner(PlannerInfo *root)
788
791
* (1) would result in a rangetable of length O(N^2) for N targets, with
789
792
* at least O(N^3) work expended here; and (2) would greatly complicate
790
793
* management of the rowMarks list.
794
+ *
795
+ * To begin with, generate a bitmapset of the relids of the subquery RTEs.
796
+ */
797
+ subqueryRTindexes = NULL ;
798
+ rti = 1 ;
799
+ foreach (lc , parse -> rtable )
800
+ {
801
+ RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lc );
802
+
803
+ if (rte -> rtekind == RTE_SUBQUERY )
804
+ subqueryRTindexes = bms_add_member (subqueryRTindexes , rti );
805
+ rti ++ ;
806
+ }
807
+
808
+ /*
809
+ * Next, we want to identify which AppendRelInfo items contain references
810
+ * to any of the aforesaid subquery RTEs. These items will need to be
811
+ * copied and modified to adjust their subquery references; whereas the
812
+ * other ones need not be touched. It's worth being tense over this
813
+ * because we can usually avoid processing most of the AppendRelInfo
814
+ * items, thereby saving O(N^2) space and time when the target is a large
815
+ * inheritance tree. We can identify AppendRelInfo items by their
816
+ * child_relid, since that should be unique within the list.
817
+ */
818
+ modifiableARIindexes = NULL ;
819
+ if (subqueryRTindexes != NULL )
820
+ {
821
+ foreach (lc , root -> append_rel_list )
822
+ {
823
+ AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
824
+
825
+ if (bms_is_member (appinfo -> parent_relid , subqueryRTindexes ) ||
826
+ bms_is_member (appinfo -> child_relid , subqueryRTindexes ) ||
827
+ bms_overlap (pull_varnos ((Node * ) appinfo -> translated_vars ),
828
+ subqueryRTindexes ))
829
+ modifiableARIindexes = bms_add_member (modifiableARIindexes ,
830
+ appinfo -> child_relid );
831
+ }
832
+ }
833
+
834
+ /*
835
+ * And now we can get on with generating a plan for each child table.
791
836
*/
792
837
foreach (lc , root -> append_rel_list )
793
838
{
794
839
AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
795
840
PlannerInfo subroot ;
796
841
Plan * subplan ;
797
- Index rti ;
798
842
799
843
/* append_rel_list contains all append rels; ignore others */
800
844
if (appinfo -> parent_relid != parentRTindex )
@@ -828,9 +872,29 @@ inheritance_planner(PlannerInfo *root)
828
872
/*
829
873
* The append_rel_list likewise might contain references to subquery
830
874
* RTEs (if any subqueries were flattenable UNION ALLs). So prepare
831
- * to apply ChangeVarNodes to that, too.
875
+ * to apply ChangeVarNodes to that, too. As explained above, we only
876
+ * want to copy items that actually contain such references; the rest
877
+ * can just get linked into the subroot's append_rel_list.
878
+ *
879
+ * If we know there are no such references, we can just use the outer
880
+ * append_rel_list unmodified.
832
881
*/
833
- subroot .append_rel_list = (List * ) copyObject (root -> append_rel_list );
882
+ if (modifiableARIindexes != NULL )
883
+ {
884
+ ListCell * lc2 ;
885
+
886
+ subroot .append_rel_list = NIL ;
887
+ foreach (lc2 , root -> append_rel_list )
888
+ {
889
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
890
+
891
+ if (bms_is_member (appinfo2 -> child_relid , modifiableARIindexes ))
892
+ appinfo2 = (AppendRelInfo * ) copyObject (appinfo2 );
893
+
894
+ subroot .append_rel_list = lappend (subroot .append_rel_list ,
895
+ appinfo2 );
896
+ }
897
+ }
834
898
835
899
/*
836
900
* Add placeholders to the child Query's rangetable list to fill the
@@ -850,7 +914,7 @@ inheritance_planner(PlannerInfo *root)
850
914
* since subquery RTEs couldn't contain any references to the target
851
915
* rel.
852
916
*/
853
- if (final_rtable != NIL )
917
+ if (final_rtable != NIL && subqueryRTindexes != NULL )
854
918
{
855
919
ListCell * lr ;
856
920
@@ -859,7 +923,7 @@ inheritance_planner(PlannerInfo *root)
859
923
{
860
924
RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lr );
861
925
862
- if (rte -> rtekind == RTE_SUBQUERY )
926
+ if (bms_is_member ( rti , subqueryRTindexes ) )
863
927
{
864
928
Index newrti ;
865
929
@@ -872,7 +936,20 @@ inheritance_planner(PlannerInfo *root)
872
936
newrti = list_length (subroot .parse -> rtable ) + 1 ;
873
937
ChangeVarNodes ((Node * ) subroot .parse , rti , newrti , 0 );
874
938
ChangeVarNodes ((Node * ) subroot .rowMarks , rti , newrti , 0 );
875
- ChangeVarNodes ((Node * ) subroot .append_rel_list , rti , newrti , 0 );
939
+ /* Skip processing unchanging parts of append_rel_list */
940
+ if (modifiableARIindexes != NULL )
941
+ {
942
+ ListCell * lc2 ;
943
+
944
+ foreach (lc2 , subroot .append_rel_list )
945
+ {
946
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
947
+
948
+ if (bms_is_member (appinfo2 -> child_relid ,
949
+ modifiableARIindexes ))
950
+ ChangeVarNodes ((Node * ) appinfo2 , rti , newrti , 0 );
951
+ }
952
+ }
876
953
rte = copyObject (rte );
877
954
subroot .parse -> rtable = lappend (subroot .parse -> rtable ,
878
955
rte );
0 commit comments