@@ -1038,7 +1038,7 @@ static void
1038
1038
inheritance_planner (PlannerInfo * root )
1039
1039
{
1040
1040
Query * parse = root -> parse ;
1041
- int parentRTindex = parse -> resultRelation ;
1041
+ int top_parentRTindex = parse -> resultRelation ;
1042
1042
Bitmapset * subqueryRTindexes ;
1043
1043
Bitmapset * modifiableARIindexes ;
1044
1044
int nominalRelation = -1 ;
@@ -1056,6 +1056,10 @@ inheritance_planner(PlannerInfo *root)
1056
1056
Index rti ;
1057
1057
RangeTblEntry * parent_rte ;
1058
1058
List * partitioned_rels = NIL ;
1059
+ PlannerInfo * parent_root ;
1060
+ Query * parent_parse ;
1061
+ Bitmapset * parent_relids = bms_make_singleton (top_parentRTindex );
1062
+ PlannerInfo * * parent_roots = NULL ;
1059
1063
1060
1064
Assert (parse -> commandType != CMD_INSERT );
1061
1065
@@ -1119,11 +1123,31 @@ inheritance_planner(PlannerInfo *root)
1119
1123
* (including the root parent) as child members of the inheritance set do
1120
1124
* not appear anywhere else in the plan. The situation is exactly the
1121
1125
* opposite in the case of non-partitioned inheritance parent as described
1122
- * below.
1126
+ * below. For the same reason, collect the list of descendant partitioned
1127
+ * tables to be saved in ModifyTable node, so that executor can lock those
1128
+ * as well.
1123
1129
*/
1124
- parent_rte = rt_fetch (parentRTindex , root -> parse -> rtable );
1130
+ parent_rte = rt_fetch (top_parentRTindex , root -> parse -> rtable );
1125
1131
if (parent_rte -> relkind == RELKIND_PARTITIONED_TABLE )
1126
- nominalRelation = parentRTindex ;
1132
+ {
1133
+ nominalRelation = top_parentRTindex ;
1134
+ partitioned_rels = get_partitioned_child_rels (root , top_parentRTindex );
1135
+ /* The root partitioned table is included as a child rel */
1136
+ Assert (list_length (partitioned_rels ) >= 1 );
1137
+ }
1138
+
1139
+ /*
1140
+ * The PlannerInfo for each child is obtained by translating the relevant
1141
+ * members of the PlannerInfo for its immediate parent, which we find
1142
+ * using the parent_relid in its AppendRelInfo. We save the PlannerInfo
1143
+ * for each parent in an array indexed by relid for fast retrieval. Since
1144
+ * the maximum number of parents is limited by the number of RTEs in the
1145
+ * query, we use that number to allocate the array. An extra entry is
1146
+ * needed since relids start from 1.
1147
+ */
1148
+ parent_roots = (PlannerInfo * * ) palloc0 ((list_length (parse -> rtable ) + 1 ) *
1149
+ sizeof (PlannerInfo * ));
1150
+ parent_roots [top_parentRTindex ] = root ;
1127
1151
1128
1152
/*
1129
1153
* And now we can get on with generating a plan for each child table.
@@ -1137,15 +1161,24 @@ inheritance_planner(PlannerInfo *root)
1137
1161
Path * subpath ;
1138
1162
1139
1163
/* append_rel_list contains all append rels; ignore others */
1140
- if (appinfo -> parent_relid != parentRTindex )
1164
+ if (! bms_is_member ( appinfo -> parent_relid , parent_relids ) )
1141
1165
continue ;
1142
1166
1167
+ /*
1168
+ * expand_inherited_rtentry() always processes a parent before any of
1169
+ * that parent's children, so the parent_root for this relation should
1170
+ * already be available.
1171
+ */
1172
+ parent_root = parent_roots [appinfo -> parent_relid ];
1173
+ Assert (parent_root != NULL );
1174
+ parent_parse = parent_root -> parse ;
1175
+
1143
1176
/*
1144
1177
* We need a working copy of the PlannerInfo so that we can control
1145
1178
* propagation of information back to the main copy.
1146
1179
*/
1147
1180
subroot = makeNode (PlannerInfo );
1148
- memcpy (subroot , root , sizeof (PlannerInfo ));
1181
+ memcpy (subroot , parent_root , sizeof (PlannerInfo ));
1149
1182
1150
1183
/*
1151
1184
* Generate modified query with this rel as target. We first apply
@@ -1154,15 +1187,15 @@ inheritance_planner(PlannerInfo *root)
1154
1187
* then fool around with subquery RTEs.
1155
1188
*/
1156
1189
subroot -> parse = (Query * )
1157
- adjust_appendrel_attrs (root ,
1158
- (Node * ) parse ,
1190
+ adjust_appendrel_attrs (parent_root ,
1191
+ (Node * ) parent_parse ,
1159
1192
1 , & appinfo );
1160
1193
1161
1194
/*
1162
1195
* If there are securityQuals attached to the parent, move them to the
1163
1196
* child rel (they've already been transformed properly for that).
1164
1197
*/
1165
- parent_rte = rt_fetch (parentRTindex , subroot -> parse -> rtable );
1198
+ parent_rte = rt_fetch (appinfo -> parent_relid , subroot -> parse -> rtable );
1166
1199
child_rte = rt_fetch (appinfo -> child_relid , subroot -> parse -> rtable );
1167
1200
child_rte -> securityQuals = parent_rte -> securityQuals ;
1168
1201
parent_rte -> securityQuals = NIL ;
@@ -1173,7 +1206,7 @@ inheritance_planner(PlannerInfo *root)
1173
1206
* executor doesn't need to see the modified copies --- we can just
1174
1207
* pass it the original rowMarks list.)
1175
1208
*/
1176
- subroot -> rowMarks = copyObject (root -> rowMarks );
1209
+ subroot -> rowMarks = copyObject (parent_root -> rowMarks );
1177
1210
1178
1211
/*
1179
1212
* The append_rel_list likewise might contain references to subquery
@@ -1190,7 +1223,7 @@ inheritance_planner(PlannerInfo *root)
1190
1223
ListCell * lc2 ;
1191
1224
1192
1225
subroot -> append_rel_list = NIL ;
1193
- foreach (lc2 , root -> append_rel_list )
1226
+ foreach (lc2 , parent_root -> append_rel_list )
1194
1227
{
1195
1228
AppendRelInfo * appinfo2 = lfirst_node (AppendRelInfo , lc2 );
1196
1229
@@ -1225,7 +1258,7 @@ inheritance_planner(PlannerInfo *root)
1225
1258
ListCell * lr ;
1226
1259
1227
1260
rti = 1 ;
1228
- foreach (lr , parse -> rtable )
1261
+ foreach (lr , parent_parse -> rtable )
1229
1262
{
1230
1263
RangeTblEntry * rte = lfirst_node (RangeTblEntry , lr );
1231
1264
@@ -1272,6 +1305,22 @@ inheritance_planner(PlannerInfo *root)
1272
1305
/* hack to mark target relation as an inheritance partition */
1273
1306
subroot -> hasInheritedTarget = true;
1274
1307
1308
+ /*
1309
+ * If the child is further partitioned, remember it as a parent. Since
1310
+ * a partitioned table does not have any data, we don't need to create
1311
+ * a plan for it. We do, however, need to remember the PlannerInfo for
1312
+ * use when processing its children.
1313
+ */
1314
+ if (child_rte -> inh )
1315
+ {
1316
+ Assert (child_rte -> relkind == RELKIND_PARTITIONED_TABLE );
1317
+ parent_relids =
1318
+ bms_add_member (parent_relids , appinfo -> child_relid );
1319
+ parent_roots [appinfo -> child_relid ] = subroot ;
1320
+
1321
+ continue ;
1322
+ }
1323
+
1275
1324
/* Generate Path(s) for accessing this result relation */
1276
1325
grouping_planner (subroot , true, 0.0 /* retrieve all tuples */ );
1277
1326
@@ -1368,13 +1417,6 @@ inheritance_planner(PlannerInfo *root)
1368
1417
Assert (!parse -> onConflict );
1369
1418
}
1370
1419
1371
- if (parent_rte -> relkind == RELKIND_PARTITIONED_TABLE )
1372
- {
1373
- partitioned_rels = get_partitioned_child_rels (root , parentRTindex );
1374
- /* The root partitioned table is included as a child rel */
1375
- Assert (list_length (partitioned_rels ) >= 1 );
1376
- }
1377
-
1378
1420
/* Result path must go into outer query's FINAL upperrel */
1379
1421
final_rel = fetch_upper_rel (root , UPPERREL_FINAL , NULL );
1380
1422
0 commit comments