diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 487373b49703fe3c6729f1c39d985fdbb590d351..e3742cf71d05c88e8e7a557144261eacc5837654 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -26,8 +26,6 @@ #include "access/relscan.h" #include "access/visibilitymap.h" -#include "catalog/pg_opfamily.h" -#include "catalog/pg_type.h" #include "executor/execdebug.h" #include "executor/nodeIndexonlyscan.h" #include "executor/nodeIndexscan.h" @@ -162,8 +160,10 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, Relation indexRel) int i; /* - * Note: we must use the index relation's tupdesc in index_getattr, - * not the slot's tupdesc, because of index_descriptor_hack(). + * Note: we must use the index relation's tupdesc in index_getattr, not + * the slot's tupdesc, in case the latter has different datatypes (this + * happens for btree name_ops in particular). They'd better have the same + * number of columns though. */ Assert(slot->tts_tupleDescriptor->natts == nindexatts); @@ -173,45 +173,6 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, Relation indexRel) ExecStoreVirtualTuple(slot); } -/* - * index_descriptor_hack -- ugly kluge to make index's tupdesc OK for slot - * - * This is necessary because, alone among btree opclasses, name_ops uses - * a storage type (cstring) different from its input type. The index - * tuple descriptor will show "cstring", which is correct, but we have to - * expose "name" as the slot datatype or ExecEvalVar will whine. If we - * ever want to have any other cases with a different storage type, we ought - * to think of a cleaner solution than this. - */ -static TupleDesc -index_descriptor_hack(Relation indexRel) -{ - TupleDesc tupdesc = RelationGetDescr(indexRel); - int i; - - /* copy so we can scribble on it safely */ - tupdesc = CreateTupleDescCopy(tupdesc); - - for (i = 0; i < tupdesc->natts; i++) - { - if (indexRel->rd_opfamily[i] == NAME_BTREE_FAM_OID && - tupdesc->attrs[i]->atttypid == CSTRINGOID) - { - tupdesc->attrs[i]->atttypid = NAMEOID; - - /* - * We set attlen to match the type OID just in case anything looks - * at it. Note that this is safe only because StoreIndexTuple - * will insert the data as a virtual tuple, and we don't expect - * anything will try to materialize the scan tuple slot. - */ - tupdesc->attrs[i]->attlen = NAMEDATALEN; - } - } - - return tupdesc; -} - /* * IndexOnlyRecheck -- access method routine to recheck a tuple in EvalPlanQual * @@ -426,9 +387,20 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* - * Initialize result tuple type. + * Build the scan tuple type using the indextlist generated by the + * planner. We use this, rather than the index's physical tuple + * descriptor, because the latter contains storage column types not the + * types of the original datums. (It's the AM's responsibility to return + * suitable data anyway.) + */ + tupDesc = ExecTypeFromTL(node->indextlist, false); + ExecAssignScanType(&indexstate->ss, tupDesc); + + /* + * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); + ExecAssignScanProjectionInfo(&indexstate->ss); /* * 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) indexstate->ioss_RelationDesc = index_open(node->indexid, relistarget ? NoLock : AccessShareLock); - /* - * Now we can get the scan tuple's type (which is the index's rowtype, - * not the heap's) and initialize result projection info. - */ - tupDesc = index_descriptor_hack(indexstate->ioss_RelationDesc); - ExecAssignScanType(&indexstate->ss, tupDesc); - ExecAssignScanProjectionInfo(&indexstate->ss); - /* * Initialize index-specific scan state */