@ -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
*/