aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-04-22 17:30:42 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-04-22 17:30:55 -0400
commitd479d00285255d422a2b38f1cfaa35808968a08c (patch)
tree67f025eded5f4661bc496e9f87d3e3b3b628fb52 /src/backend/executor
parent197d33ccbe888fc84ae4e49bb241e88ea3c81f15 (diff)
downloadpostgresql-d479d00285255d422a2b38f1cfaa35808968a08c.tar.gz
postgresql-d479d00285255d422a2b38f1cfaa35808968a08c.zip
Don't crash on reference to an un-available system column.
Adopt a more consistent policy about what slot-type-specific getsysattr functions should do when system attributes are not available. To wit, they should all throw the same user-oriented error, rather than variously crashing or emitting developer-oriented messages. This closes a identifiable problem in commits a71cfc56b and 3fb93103a (in v13 and v12), so back-patch into those branches, along with a test case to try to ensure we don't break it again. It is not known that any of the former crash cases are reachable in HEAD, but this seems like a good safety improvement in any case. Discussion: https://postgr.es/m/141051591267657@mail.yandex.ru
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execTuples.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 73c35df9c96..f4478028431 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -122,9 +122,8 @@ tts_virtual_clear(TupleTableSlot *slot)
}
/*
- * Attribute values are readily available in tts_values and tts_isnull array
- * in a VirtualTupleTableSlot. So there should be no need to call either of the
- * following two functions.
+ * VirtualTupleTableSlots always have fully populated tts_values and
+ * tts_isnull arrays. So this function should never be called.
*/
static void
tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
@@ -132,10 +131,19 @@ tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
}
+/*
+ * VirtualTupleTableSlots never provide system attributes (except those
+ * handled generically, such as tableoid). We generally shouldn't get
+ * here, but provide a user-friendly message if we do.
+ */
static Datum
tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
{
- elog(ERROR, "virtual tuple table slot does not have system attributes");
+ Assert(!TTS_EMPTY(slot));
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot retrieve a system column in this context")));
return 0; /* silence compiler warnings */
}
@@ -335,6 +343,15 @@ tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Assert(!TTS_EMPTY(slot));
+ /*
+ * In some code paths it's possible to get here with a non-materialized
+ * slot, in which case we can't retrieve system columns.
+ */
+ if (!hslot->tuple)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot retrieve a system column in this context")));
+
return heap_getsysattr(hslot->tuple, attnum,
slot->tts_tupleDescriptor, isnull);
}
@@ -497,7 +514,11 @@ tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
static Datum
tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
{
- elog(ERROR, "minimal tuple table slot does not have system attributes");
+ Assert(!TTS_EMPTY(slot));
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot retrieve a system column in this context")));
return 0; /* silence compiler warnings */
}
@@ -681,6 +702,15 @@ tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Assert(!TTS_EMPTY(slot));
+ /*
+ * In some code paths it's possible to get here with a non-materialized
+ * slot, in which case we can't retrieve system columns.
+ */
+ if (!bslot->base.tuple)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot retrieve a system column in this context")));
+
return heap_getsysattr(bslot->base.tuple, attnum,
slot->tts_tupleDescriptor, isnull);
}