Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2b81444

Browse files
committed
Make ExecGetInsertedCols() and friends more robust and improve comments.
If ExecGetInsertedCols(), ExecGetUpdatedCols() or ExecGetExtraUpdatedCols() were called with a ResultRelInfo that's not in the range table and isn't a partition routing target, the functions would dereference a NULL pointer, relinfo->ri_RootResultRelInfo. Such ResultRelInfos are created when firing RI triggers in tables that are not modified directly. None of the current callers of these functions pass such relations, so this isn't a live bug, but let's make them more robust. Also update comment in ResultRelInfo; after commit 6214e2b, ri_RangeTableIndex is zero for ResultRelInfos created for partition tuple routing. Noted by Coverity. Backpatch down to v11, like commit 6214e2b. Reviewed-by: Tom Lane, Amit Langote
1 parent a27f3a7 commit 2b81444

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

src/backend/executor/execUtils.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,18 +1182,18 @@ Bitmapset *
11821182
ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
11831183
{
11841184
/*
1185-
* The columns are stored in the range table entry. If this ResultRelInfo
1186-
* doesn't have an entry in the range table (i.e. if it represents a
1187-
* partition routing target), fetch the parent's RTE and map the columns
1188-
* to the order they are in the partition.
1185+
* The columns are stored in the range table entry. If this ResultRelInfo
1186+
* represents a partition routing target, and doesn't have an entry of its
1187+
* own in the range table, fetch the parent's RTE and map the columns to
1188+
* the order they are in the partition.
11891189
*/
11901190
if (relinfo->ri_RangeTableIndex != 0)
11911191
{
11921192
RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
11931193

11941194
return rte->insertedCols;
11951195
}
1196-
else
1196+
else if (relinfo->ri_RootResultRelInfo)
11971197
{
11981198
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
11991199
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1205,6 +1205,16 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
12051205
else
12061206
return rte->insertedCols;
12071207
}
1208+
else
1209+
{
1210+
/*
1211+
* The relation isn't in the range table and it isn't a partition
1212+
* routing target. This ResultRelInfo must've been created only for
1213+
* firing triggers and the relation is not being inserted into. (See
1214+
* ExecGetTriggerResultRel.)
1215+
*/
1216+
return NULL;
1217+
}
12081218
}
12091219

12101220
/* Return a bitmap representing columns being updated */
@@ -1218,7 +1228,7 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12181228

12191229
return rte->updatedCols;
12201230
}
1221-
else
1231+
else if (relinfo->ri_RootResultRelInfo)
12221232
{
12231233
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12241234
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1230,6 +1240,8 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12301240
else
12311241
return rte->updatedCols;
12321242
}
1243+
else
1244+
return NULL;
12331245
}
12341246

12351247
/* Return a bitmap representing generated columns being updated */
@@ -1243,7 +1255,7 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12431255

12441256
return rte->extraUpdatedCols;
12451257
}
1246-
else
1258+
else if (relinfo->ri_RootResultRelInfo)
12471259
{
12481260
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12491261
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1255,6 +1267,8 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12551267
else
12561268
return rte->extraUpdatedCols;
12571269
}
1270+
else
1271+
return NULL;
12581272
}
12591273

12601274
/* Return columns being updated, including generated columns */

src/include/nodes/execnodes.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,15 @@ typedef struct OnConflictSetState
392392
* relation, and perhaps also fire triggers. ResultRelInfo holds all the
393393
* information needed about a result relation, including indexes.
394394
*
395-
* Normally, a ResultRelInfo refers to a table that is in the query's
396-
* range table; then ri_RangeTableIndex is the RT index and ri_RelationDesc
397-
* is just a copy of the relevant es_relations[] entry. But sometimes,
398-
* in ResultRelInfos used only for triggers, ri_RangeTableIndex is zero
399-
* and ri_RelationDesc is a separately-opened relcache pointer that needs
400-
* to be separately closed. See ExecGetTriggerResultRel.
395+
* Normally, a ResultRelInfo refers to a table that is in the query's range
396+
* table; then ri_RangeTableIndex is the RT index and ri_RelationDesc is
397+
* just a copy of the relevant es_relations[] entry. However, in some
398+
* situations we create ResultRelInfos for relations that are not in the
399+
* range table, namely for targets of tuple routing in a partitioned table,
400+
* and when firing triggers in tables other than the target tables (See
401+
* ExecGetTriggerResultRel). In these situations, ri_RangeTableIndex is 0
402+
* and ri_RelationDesc is a separately-opened relcache pointer that needs to
403+
* be separately closed.
401404
*/
402405
typedef struct ResultRelInfo
403406
{

0 commit comments

Comments
 (0)