@@ -834,7 +834,9 @@ inheritance_planner(PlannerInfo *root)
834
834
{
835
835
Query * parse = root -> parse ;
836
836
int parentRTindex = parse -> resultRelation ;
837
- Bitmapset * resultRTindexes = NULL ;
837
+ Bitmapset * resultRTindexes ;
838
+ Bitmapset * subqueryRTindexes ;
839
+ Bitmapset * modifiableARIindexes ;
838
840
int nominalRelation = -1 ;
839
841
List * final_rtable = NIL ;
840
842
int save_rel_array_size = 0 ;
@@ -845,6 +847,7 @@ inheritance_planner(PlannerInfo *root)
845
847
List * returningLists = NIL ;
846
848
List * rowMarks ;
847
849
ListCell * lc ;
850
+ Index rti ;
848
851
849
852
Assert (parse -> commandType != CMD_INSERT );
850
853
@@ -867,8 +870,10 @@ inheritance_planner(PlannerInfo *root)
867
870
* subqueries during planning, and so we must create copies of them too,
868
871
* except where they are target relations, which will each only be used in
869
872
* a single plan.
873
+ *
874
+ * To begin with, we'll need a bitmapset of the target relation relids.
870
875
*/
871
- resultRTindexes = bms_add_member ( resultRTindexes , parentRTindex );
876
+ resultRTindexes = bms_make_singleton ( parentRTindex );
872
877
foreach (lc , root -> append_rel_list )
873
878
{
874
879
AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
@@ -878,12 +883,57 @@ inheritance_planner(PlannerInfo *root)
878
883
appinfo -> child_relid );
879
884
}
880
885
886
+ /*
887
+ * Now, generate a bitmapset of the relids of the subquery RTEs, including
888
+ * security-barrier RTEs that will become subqueries, as just explained.
889
+ */
890
+ subqueryRTindexes = NULL ;
891
+ rti = 1 ;
892
+ foreach (lc , parse -> rtable )
893
+ {
894
+ RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lc );
895
+
896
+ if (rte -> rtekind == RTE_SUBQUERY ||
897
+ (rte -> securityQuals != NIL &&
898
+ !bms_is_member (rti , resultRTindexes )))
899
+ subqueryRTindexes = bms_add_member (subqueryRTindexes , rti );
900
+ rti ++ ;
901
+ }
902
+
903
+ /*
904
+ * Next, we want to identify which AppendRelInfo items contain references
905
+ * to any of the aforesaid subquery RTEs. These items will need to be
906
+ * copied and modified to adjust their subquery references; whereas the
907
+ * other ones need not be touched. It's worth being tense over this
908
+ * because we can usually avoid processing most of the AppendRelInfo
909
+ * items, thereby saving O(N^2) space and time when the target is a large
910
+ * inheritance tree. We can identify AppendRelInfo items by their
911
+ * child_relid, since that should be unique within the list.
912
+ */
913
+ modifiableARIindexes = NULL ;
914
+ if (subqueryRTindexes != NULL )
915
+ {
916
+ foreach (lc , root -> append_rel_list )
917
+ {
918
+ AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
919
+
920
+ if (bms_is_member (appinfo -> parent_relid , subqueryRTindexes ) ||
921
+ bms_is_member (appinfo -> child_relid , subqueryRTindexes ) ||
922
+ bms_overlap (pull_varnos ((Node * ) appinfo -> translated_vars ),
923
+ subqueryRTindexes ))
924
+ modifiableARIindexes = bms_add_member (modifiableARIindexes ,
925
+ appinfo -> child_relid );
926
+ }
927
+ }
928
+
929
+ /*
930
+ * And now we can get on with generating a plan for each child table.
931
+ */
881
932
foreach (lc , root -> append_rel_list )
882
933
{
883
934
AppendRelInfo * appinfo = (AppendRelInfo * ) lfirst (lc );
884
935
PlannerInfo subroot ;
885
936
Plan * subplan ;
886
- Index rti ;
887
937
888
938
/* append_rel_list contains all append rels; ignore others */
889
939
if (appinfo -> parent_relid != parentRTindex )
@@ -917,9 +967,29 @@ inheritance_planner(PlannerInfo *root)
917
967
/*
918
968
* The append_rel_list likewise might contain references to subquery
919
969
* RTEs (if any subqueries were flattenable UNION ALLs). So prepare
920
- * to apply ChangeVarNodes to that, too.
970
+ * to apply ChangeVarNodes to that, too. As explained above, we only
971
+ * want to copy items that actually contain such references; the rest
972
+ * can just get linked into the subroot's append_rel_list.
973
+ *
974
+ * If we know there are no such references, we can just use the outer
975
+ * append_rel_list unmodified.
921
976
*/
922
- subroot .append_rel_list = (List * ) copyObject (root -> append_rel_list );
977
+ if (modifiableARIindexes != NULL )
978
+ {
979
+ ListCell * lc2 ;
980
+
981
+ subroot .append_rel_list = NIL ;
982
+ foreach (lc2 , root -> append_rel_list )
983
+ {
984
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
985
+
986
+ if (bms_is_member (appinfo2 -> child_relid , modifiableARIindexes ))
987
+ appinfo2 = (AppendRelInfo * ) copyObject (appinfo2 );
988
+
989
+ subroot .append_rel_list = lappend (subroot .append_rel_list ,
990
+ appinfo2 );
991
+ }
992
+ }
923
993
924
994
/*
925
995
* Add placeholders to the child Query's rangetable list to fill the
@@ -933,13 +1003,13 @@ inheritance_planner(PlannerInfo *root)
933
1003
934
1004
/*
935
1005
* If this isn't the first child Query, generate duplicates of all
936
- * subquery RTEs, and adjust Var numbering to reference the
937
- * duplicates. To simplify the loop logic, we scan the original rtable
938
- * not the copy just made by adjust_appendrel_attrs; that should be OK
939
- * since subquery RTEs couldn't contain any references to the target
940
- * rel.
1006
+ * subquery (or subquery-to-be) RTEs, and adjust Var numbering to
1007
+ * reference the duplicates. To simplify the loop logic, we scan the
1008
+ * original rtable not the copy just made by adjust_appendrel_attrs;
1009
+ * that should be OK since subquery RTEs couldn't contain any
1010
+ * references to the target rel.
941
1011
*/
942
- if (final_rtable != NIL )
1012
+ if (final_rtable != NIL && subqueryRTindexes != NULL )
943
1013
{
944
1014
ListCell * lr ;
945
1015
@@ -948,14 +1018,7 @@ inheritance_planner(PlannerInfo *root)
948
1018
{
949
1019
RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lr );
950
1020
951
- /*
952
- * Copy subquery RTEs and RTEs with security barrier quals
953
- * that will be turned into subqueries, except those that are
954
- * target relations.
955
- */
956
- if (rte -> rtekind == RTE_SUBQUERY ||
957
- (rte -> securityQuals != NIL &&
958
- !bms_is_member (rti , resultRTindexes )))
1021
+ if (bms_is_member (rti , subqueryRTindexes ))
959
1022
{
960
1023
Index newrti ;
961
1024
@@ -968,7 +1031,20 @@ inheritance_planner(PlannerInfo *root)
968
1031
newrti = list_length (subroot .parse -> rtable ) + 1 ;
969
1032
ChangeVarNodes ((Node * ) subroot .parse , rti , newrti , 0 );
970
1033
ChangeVarNodes ((Node * ) subroot .rowMarks , rti , newrti , 0 );
971
- ChangeVarNodes ((Node * ) subroot .append_rel_list , rti , newrti , 0 );
1034
+ /* Skip processing unchanging parts of append_rel_list */
1035
+ if (modifiableARIindexes != NULL )
1036
+ {
1037
+ ListCell * lc2 ;
1038
+
1039
+ foreach (lc2 , subroot .append_rel_list )
1040
+ {
1041
+ AppendRelInfo * appinfo2 = (AppendRelInfo * ) lfirst (lc2 );
1042
+
1043
+ if (bms_is_member (appinfo2 -> child_relid ,
1044
+ modifiableARIindexes ))
1045
+ ChangeVarNodes ((Node * ) appinfo2 , rti , newrti , 0 );
1046
+ }
1047
+ }
972
1048
rte = copyObject (rte );
973
1049
ChangeVarNodes ((Node * ) rte -> securityQuals , rti , newrti , 0 );
974
1050
subroot .parse -> rtable = lappend (subroot .parse -> rtable ,
0 commit comments