@@ -787,6 +787,8 @@ inheritance_planner(PlannerInfo *root)
787
787
{
788
788
Query * parse = root -> parse ;
789
789
int parentRTindex = parse -> resultRelation ;
790
+ Bitmapset * subqueryRTindexes ;
791
+ Bitmapset * modifiableARIindexes ;
790
792
List * final_rtable = NIL ;
791
793
int save_rel_array_size = 0 ;
792
794
RelOptInfo * * save_rel_array = NULL ;
@@ -796,6 +798,7 @@ inheritance_planner(PlannerInfo *root)
796
798
List * returningLists = NIL ;
797
799
List * rowMarks ;
798
800
ListCell * lc ;
801
+ Index rti ;
799
802
800
803
/*
801
804
* We generate a modified instance of the original Query for each target
@@ -811,13 +814,54 @@ inheritance_planner(PlannerInfo *root)
811
814
* (1) would result in a rangetable of length O(N^2) for N targets, with
812
815
* at least O(N^3) work expended here; and (2) would greatly complicate
813
816
* management of the rowMarks list.
817
+ *
818
+ * To begin with, generate a bitmapset of the relids of the subquery RTEs.
819
+ */
820
+ subqueryRTindexes = NULL ;
821
+ rti = 1 ;
822
+ foreach (lc , parse -> rtable )
823
+ {
824
+ RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lc );
825
+
826
+ if (rte -> rtekind == RTE_SUBQUERY )
827
+ subqueryRTindexes = bms_add_member (subqueryRTindexes , rti );
828
+ rti ++ ;
829
+ }
830
+
831
+ /*
832
+ * Next, we want to identify which AppendRelInfo items contain references
833
+ * to any of the aforesaid subquery RTEs. These items will need to be
834
+ * copied and modified to adjust their subquery references; whereas the
835
+ * other ones need not be touched. It's worth being tense over this
836
+ * because we can usually avoid processing most of the AppendRelInfo
837
+ * items, thereby saving O(N^2) space and time when the target is a large
838
+ * inheritance tree. We can identify AppendRelInfo items by their
839
+ * child_relid, since that should be unique within the list.
840
+ */
841
+ modifiableARIindexes = NULL ;
842
+ if (subqueryRTindexes != NULL )
843
+ {
844
+ foreach (lc , root -> append_rel_list )
845
+ {
846
+ AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
847
+
848
+ if (bms_is_member (appinfo -> parent_relid , subqueryRTindexes ) ||
849
+ bms_is_member (appinfo -> child_relid , subqueryRTindexes ) ||
850
+ bms_overlap (pull_varnos ((Node * ) appinfo -> translated_vars ),
851
+ subqueryRTindexes ))
852
+ modifiableARIindexes = bms_add_member (modifiableARIindexes ,
853
+ appinfo -> child_relid );
854
+ }
855
+ }
856
+
857
+ /*
858
+ * And now we can get on with generating a plan for each child table.
814
859
*/
815
860
foreach (lc , root -> append_rel_list )
816
861
{
817
862
AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
818
863
PlannerInfo subroot ;
819
864
Plan * subplan ;
820
- Index rti ;
821
865
822
866
/* append_rel_list contains all append rels; ignore others */
823
867
if (appinfo -> parent_relid != parentRTindex )
@@ -851,9 +895,29 @@ inheritance_planner(PlannerInfo *root)
851
895
/*
852
896
* The append_rel_list likewise might contain references to subquery
853
897
* RTEs (if any subqueries were flattenable UNION ALLs). So prepare
854
- * to apply ChangeVarNodes to that, too.
898
+ * to apply ChangeVarNodes to that, too. As explained above, we only
899
+ * want to copy items that actually contain such references; the rest
900
+ * can just get linked into the subroot's append_rel_list.
901
+ *
902
+ * If we know there are no such references, we can just use the outer
903
+ * append_rel_list unmodified.
855
904
*/
856
- subroot .append_rel_list = (List * ) copyObject (root -> append_rel_list );
905
+ if (modifiableARIindexes != NULL )
906
+ {
907
+ ListCell * lc2 ;
908
+
909
+ subroot .append_rel_list = NIL ;
910
+ foreach (lc2 , root -> append_rel_list )
911
+ {
912
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
913
+
914
+ if (bms_is_member (appinfo2 -> child_relid , modifiableARIindexes ))
915
+ appinfo2 = (AppendRelInfo * ) copyObject (appinfo2 );
916
+
917
+ subroot .append_rel_list = lappend (subroot .append_rel_list ,
918
+ appinfo2 );
919
+ }
920
+ }
857
921
858
922
/*
859
923
* Add placeholders to the child Query's rangetable list to fill the
@@ -873,7 +937,7 @@ inheritance_planner(PlannerInfo *root)
873
937
* since subquery RTEs couldn't contain any references to the target
874
938
* rel.
875
939
*/
876
- if (final_rtable != NIL )
940
+ if (final_rtable != NIL && subqueryRTindexes != NULL )
877
941
{
878
942
ListCell * lr ;
879
943
@@ -882,7 +946,7 @@ inheritance_planner(PlannerInfo *root)
882
946
{
883
947
RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lr );
884
948
885
- if (rte -> rtekind == RTE_SUBQUERY )
949
+ if (bms_is_member ( rti , subqueryRTindexes ) )
886
950
{
887
951
Index newrti ;
888
952
@@ -895,7 +959,20 @@ inheritance_planner(PlannerInfo *root)
895
959
newrti = list_length (subroot .parse -> rtable ) + 1 ;
896
960
ChangeVarNodes ((Node * ) subroot .parse , rti , newrti , 0 );
897
961
ChangeVarNodes ((Node * ) subroot .rowMarks , rti , newrti , 0 );
898
- ChangeVarNodes ((Node * ) subroot .append_rel_list , rti , newrti , 0 );
962
+ /* Skip processing unchanging parts of append_rel_list */
963
+ if (modifiableARIindexes != NULL )
964
+ {
965
+ ListCell * lc2 ;
966
+
967
+ foreach (lc2 , subroot .append_rel_list )
968
+ {
969
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
970
+
971
+ if (bms_is_member (appinfo2 -> child_relid ,
972
+ modifiableARIindexes ))
973
+ ChangeVarNodes ((Node * ) appinfo2 , rti , newrti , 0 );
974
+ }
975
+ }
899
976
rte = copyObject (rte );
900
977
subroot .parse -> rtable = lappend (subroot .parse -> rtable ,
901
978
rte );
0 commit comments