Skip to content

Commit 18cacf8

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 6214e2b228, ri_RangeTableIndex is zero for ResultRelInfos created for partition tuple routing. Noted by Coverity. Backpatch down to v11, like commit 6214e2b228. Reviewed-by: Tom Lane, Amit Langote
1 parent 6c23e5a commit 18cacf8

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
@@ -1210,18 +1210,18 @@ Bitmapset *
12101210
ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
12111211
{
12121212
/*
1213-
* The columns are stored in the range table entry. If this ResultRelInfo
1214-
* doesn't have an entry in the range table (i.e. if it represents a
1215-
* partition routing target), fetch the parent's RTE and map the columns
1216-
* to the order they are in the partition.
1213+
* The columns are stored in the range table entry. If this ResultRelInfo
1214+
* represents a partition routing target, and doesn't have an entry of its
1215+
* own in the range table, fetch the parent's RTE and map the columns to
1216+
* the order they are in the partition.
12171217
*/
12181218
if (relinfo->ri_RangeTableIndex != 0)
12191219
{
12201220
RangeTblEntry *rte = exec_rt_fetch(relinfo->ri_RangeTableIndex, estate);
12211221

12221222
return rte->insertedCols;
12231223
}
1224-
else
1224+
else if (relinfo->ri_RootResultRelInfo)
12251225
{
12261226
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12271227
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1233,6 +1233,16 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
12331233
else
12341234
return rte->insertedCols;
12351235
}
1236+
else
1237+
{
1238+
/*
1239+
* The relation isn't in the range table and it isn't a partition
1240+
* routing target. This ResultRelInfo must've been created only for
1241+
* firing triggers and the relation is not being inserted into. (See
1242+
* ExecGetTriggerResultRel.)
1243+
*/
1244+
return NULL;
1245+
}
12361246
}
12371247

12381248
/* Return a bitmap representing columns being updated */
@@ -1246,7 +1256,7 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12461256

12471257
return rte->updatedCols;
12481258
}
1249-
else
1259+
else if (relinfo->ri_RootResultRelInfo)
12501260
{
12511261
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12521262
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1258,6 +1268,8 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12581268
else
12591269
return rte->updatedCols;
12601270
}
1271+
else
1272+
return NULL;
12611273
}
12621274

12631275
/* Return a bitmap representing generated columns being updated */
@@ -1271,7 +1283,7 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12711283

12721284
return rte->extraUpdatedCols;
12731285
}
1274-
else
1286+
else if (relinfo->ri_RootResultRelInfo)
12751287
{
12761288
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12771289
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
@@ -1283,6 +1295,8 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
12831295
else
12841296
return rte->extraUpdatedCols;
12851297
}
1298+
else
1299+
return NULL;
12861300
}
12871301

12881302
/* 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
@@ -395,12 +395,15 @@ typedef struct OnConflictSetState
395395
* relation, and perhaps also fire triggers. ResultRelInfo holds all the
396396
* information needed about a result relation, including indexes.
397397
*
398-
* Normally, a ResultRelInfo refers to a table that is in the query's
399-
* range table; then ri_RangeTableIndex is the RT index and ri_RelationDesc
400-
* is just a copy of the relevant es_relations[] entry. But sometimes,
401-
* in ResultRelInfos used only for triggers, ri_RangeTableIndex is zero
402-
* and ri_RelationDesc is a separately-opened relcache pointer that needs
403-
* to be separately closed. See ExecGetTriggerResultRel.
398+
* Normally, a ResultRelInfo refers to a table that is in the query's range
399+
* table; then ri_RangeTableIndex is the RT index and ri_RelationDesc is
400+
* just a copy of the relevant es_relations[] entry. However, in some
401+
* situations we create ResultRelInfos for relations that are not in the
402+
* range table, namely for targets of tuple routing in a partitioned table,
403+
* and when firing triggers in tables other than the target tables (See
404+
* ExecGetTriggerResultRel). In these situations, ri_RangeTableIndex is 0
405+
* and ri_RelationDesc is a separately-opened relcache pointer that needs to
406+
* be separately closed.
404407
*/
405408
typedef struct ResultRelInfo
406409
{

0 commit comments

Comments
 (0)