From ba0c2f4045a58c2d11e12d5f0e5d770765be6c82 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Wed, 24 Apr 2024 14:14:44 +1200 Subject: [PATCH v2] Ensure we allocate NAMEDATALEN bytes for names in Index Only Scans --- src/backend/executor/nodeIndexonlyscan.c | 55 ++++++++++++++++++++++-- src/include/nodes/execnodes.h | 4 ++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index fcf6d1d932..93ab69ba50 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -45,8 +45,8 @@ static TupleTableSlot *IndexOnlyNext(IndexOnlyScanState *node); -static void StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, - TupleDesc itupdesc); +static void StoreIndexTuple(IndexOnlyScanState *node, TupleTableSlot *slot, + IndexTuple itup, TupleDesc itupdesc); /* ---------------------------------------------------------------- @@ -205,7 +205,7 @@ IndexOnlyNext(IndexOnlyScanState *node) ExecForceStoreHeapTuple(scandesc->xs_hitup, slot, false); } else if (scandesc->xs_itup) - StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc); + StoreIndexTuple(node, slot, scandesc->xs_itup, scandesc->xs_itupdesc); else elog(ERROR, "no data returned for index-only scan"); @@ -263,7 +263,8 @@ IndexOnlyNext(IndexOnlyScanState *node) * right now we don't need it elsewhere. */ static void -StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, TupleDesc itupdesc) +StoreIndexTuple(IndexOnlyScanState *node, TupleTableSlot *slot, + IndexTuple itup, TupleDesc itupdesc) { /* * Note: we must use the tupdesc supplied by the AM in index_deform_tuple, @@ -276,6 +277,26 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, TupleDesc itupdesc) ExecClearTuple(slot); index_deform_tuple(itup, itupdesc, slot->tts_values, slot->tts_isnull); + + if (node->ioss_ConvertDatumIdxs != NULL) + { + for (int i = 0; i < node->ioss_ConvertDatumCount; i++) + { + int j = node->ioss_ConvertDatumIdxs[i]; + Name name; + + /* skip null Datums */ + if (slot->tts_isnull[j]) + continue; + + name = (Name) MemoryContextAlloc(node->ss.ps.ps_ExprContext->ecxt_per_tuple_memory, + NAMEDATALEN); + + namestrcpy(name, DatumGetCString(slot->tts_values[j])); + slot->tts_values[j] = NameGetDatum(name); + } + } + ExecStoreVirtualTuple(slot); } @@ -603,6 +624,32 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) indexstate->ioss_RuntimeContext = NULL; } + indexstate->ioss_ConvertDatumIdxs = NULL; + indexstate->ioss_ConvertDatumCount = 0; + + { + int name_count = 0; + for (int i = 0; i < tupDesc->natts; i++) + { + if (tupDesc->attrs[i].atttypid == NAMEOID) + name_count++; + } + + if (name_count > 0) + { + int j = 0; + indexstate->ioss_ConvertDatumIdxs = palloc(sizeof(int) * name_count); + + for (int i = 0; i < tupDesc->natts; i++) + { + if (tupDesc->attrs[i].atttypid == NAMEOID) + indexstate->ioss_ConvertDatumIdxs[j++] = i; + } + } + + indexstate->ioss_ConvertDatumCount = name_count; + } + /* * all done. */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index d927ac44a8..6d72e04fe7 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1690,6 +1690,8 @@ typedef struct IndexScanState * TableSlot slot for holding tuples fetched from the table * VMBuffer buffer in use for visibility map testing, if any * PscanLen size of parallel index-only scan descriptor + * ConvertDatumIdxs Index of Datums from the index to convert to heap type + * ConvertDatumCount Number of elements in ConvertDatumIdxs * ---------------- */ typedef struct IndexOnlyScanState @@ -1709,6 +1711,8 @@ typedef struct IndexOnlyScanState TupleTableSlot *ioss_TableSlot; Buffer ioss_VMBuffer; Size ioss_PscanLen; + int *ioss_ConvertDatumIdxs; + int ioss_ConvertDatumCount; } IndexOnlyScanState; /* ---------------- -- 2.40.1.windows.1