Skip to content

Commit cb6771f

Browse files
committed
Generate index-only scan tuple descriptor from the plan node's indextlist.
Dept. of second thoughts: as long as we've got that tlist hanging around anyway, we can apply ExecTypeFromTL to it to get a suitable descriptor for the ScanTupleSlot. This is a nicer solution than the previous one because it eliminates some hard-wired knowledge about btree name_ops, and because it avoids the somewhat shaky assumption that we needn't set up the scan tuple descriptor in EXPLAIN_ONLY mode. It doesn't change what actually happens at run-time though, and I'm still a bit nervous about that.
1 parent e991930 commit cb6771f

File tree

1 file changed

+16
-52
lines changed

1 file changed

+16
-52
lines changed

src/backend/executor/nodeIndexonlyscan.c

+16-52
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626

2727
#include "access/relscan.h"
2828
#include "access/visibilitymap.h"
29-
#include "catalog/pg_opfamily.h"
30-
#include "catalog/pg_type.h"
3129
#include "executor/execdebug.h"
3230
#include "executor/nodeIndexonlyscan.h"
3331
#include "executor/nodeIndexscan.h"
@@ -162,8 +160,10 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, Relation indexRel)
162160
int i;
163161

164162
/*
165-
* Note: we must use the index relation's tupdesc in index_getattr,
166-
* not the slot's tupdesc, because of index_descriptor_hack().
163+
* Note: we must use the index relation's tupdesc in index_getattr, not
164+
* the slot's tupdesc, in case the latter has different datatypes (this
165+
* happens for btree name_ops in particular). They'd better have the same
166+
* number of columns though.
167167
*/
168168
Assert(slot->tts_tupleDescriptor->natts == nindexatts);
169169

@@ -173,45 +173,6 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, Relation indexRel)
173173
ExecStoreVirtualTuple(slot);
174174
}
175175

176-
/*
177-
* index_descriptor_hack -- ugly kluge to make index's tupdesc OK for slot
178-
*
179-
* This is necessary because, alone among btree opclasses, name_ops uses
180-
* a storage type (cstring) different from its input type. The index
181-
* tuple descriptor will show "cstring", which is correct, but we have to
182-
* expose "name" as the slot datatype or ExecEvalVar will whine. If we
183-
* ever want to have any other cases with a different storage type, we ought
184-
* to think of a cleaner solution than this.
185-
*/
186-
static TupleDesc
187-
index_descriptor_hack(Relation indexRel)
188-
{
189-
TupleDesc tupdesc = RelationGetDescr(indexRel);
190-
int i;
191-
192-
/* copy so we can scribble on it safely */
193-
tupdesc = CreateTupleDescCopy(tupdesc);
194-
195-
for (i = 0; i < tupdesc->natts; i++)
196-
{
197-
if (indexRel->rd_opfamily[i] == NAME_BTREE_FAM_OID &&
198-
tupdesc->attrs[i]->atttypid == CSTRINGOID)
199-
{
200-
tupdesc->attrs[i]->atttypid = NAMEOID;
201-
202-
/*
203-
* We set attlen to match the type OID just in case anything looks
204-
* at it. Note that this is safe only because StoreIndexTuple
205-
* will insert the data as a virtual tuple, and we don't expect
206-
* anything will try to materialize the scan tuple slot.
207-
*/
208-
tupdesc->attrs[i]->attlen = NAMEDATALEN;
209-
}
210-
}
211-
212-
return tupdesc;
213-
}
214-
215176
/*
216177
* IndexOnlyRecheck -- access method routine to recheck a tuple in EvalPlanQual
217178
*
@@ -426,9 +387,20 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
426387
indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
427388

428389
/*
429-
* Initialize result tuple type.
390+
* Build the scan tuple type using the indextlist generated by the
391+
* planner. We use this, rather than the index's physical tuple
392+
* descriptor, because the latter contains storage column types not the
393+
* types of the original datums. (It's the AM's responsibility to return
394+
* suitable data anyway.)
395+
*/
396+
tupDesc = ExecTypeFromTL(node->indextlist, false);
397+
ExecAssignScanType(&indexstate->ss, tupDesc);
398+
399+
/*
400+
* Initialize result tuple type and projection info.
430401
*/
431402
ExecAssignResultTypeFromTL(&indexstate->ss.ps);
403+
ExecAssignScanProjectionInfo(&indexstate->ss);
432404

433405
/*
434406
* If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
@@ -449,14 +421,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
449421
indexstate->ioss_RelationDesc = index_open(node->indexid,
450422
relistarget ? NoLock : AccessShareLock);
451423

452-
/*
453-
* Now we can get the scan tuple's type (which is the index's rowtype,
454-
* not the heap's) and initialize result projection info.
455-
*/
456-
tupDesc = index_descriptor_hack(indexstate->ioss_RelationDesc);
457-
ExecAssignScanType(&indexstate->ss, tupDesc);
458-
ExecAssignScanProjectionInfo(&indexstate->ss);
459-
460424
/*
461425
* Initialize index-specific scan state
462426
*/

0 commit comments

Comments
 (0)