diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index aa5b28c..6316ca5 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -180,6 +180,7 @@ BuildIndexValueDescription(Relation indexRelation,
 	Oid			indexrelid = RelationGetRelid(indexRelation);
 	Oid			indrelid;
 	AclResult	aclresult;
+	//	elog(NOTICE, "BuildIndexValueDescription. begin");
 
 	/*
 	 * Check permissions- if the user does not have access to view all of the
@@ -221,6 +222,7 @@ BuildIndexValueDescription(Relation indexRelation,
 		for (keyno = 0; keyno < idxrec->indnatts; keyno++)
 		{
 			AttrNumber	attnum = idxrec->indkey.values[keyno];
+			//elog(NOTICE, "BuildIndexValueDescription. keyno %d", keyno);
 
 			/*
 			 * Note that if attnum == InvalidAttrNumber, then this is an index
@@ -244,30 +246,40 @@ BuildIndexValueDescription(Relation indexRelation,
 	appendStringInfo(&buf, "(%s)=(",
 					 pg_get_indexdef_columns(indexrelid, true));
 
+	int nkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
 	for (i = 0; i < natts; i++)
 	{
 		char	   *val;
-
 		if (isnull[i])
 			val = "null";
 		else
 		{
 			Oid			foutoid;
 			bool		typisvarlena;
+			TupleDesc	tupdesc = RelationGetDescr(indexRelation);
+			if (i < nkeyatts)
+			{
+				/* TODO
+				* The provided data is not necessarily of the type stored in the
+				* index; rather it is of the index opclass's input type. So look
+				* at rd_opcintype not the index tupdesc.
+				*
+				* Note: this is a bit shaky for opclasses that have pseudotype
+				* input types such as ANYARRAY or RECORD.  Currently, the
+				* typoutput functions associated with the pseudotypes will work
+				* okay, but we might have to try harder in future.
+				*/
+				//elog(NOTICE, "BuildIndexValueDescription. tdtypeid[%d]=%u rd_opcintype[%d]=%u", i, tupdesc->attrs[i]->atttypid,i, indexRelation->rd_opcintype[i]);
+				getTypeOutputInfo(indexRelation->rd_opcintype[i], &foutoid, &typisvarlena);
+				val = OidOutputFunctionCall(foutoid, values[i]);
+			}
+			else
+			{
+				getTypeOutputInfo(tupdesc->attrs[i]->atttypid, &foutoid, &typisvarlena);
+				val = OidOutputFunctionCall(foutoid, values[i]);
+				//elog(NOTICE, "BuildIndexValueDescription. some included value [%d]", i);
 
-			/*
-			 * The provided data is not necessarily of the type stored in the
-			 * index; rather it is of the index opclass's input type. So look
-			 * at rd_opcintype not the index tupdesc.
-			 *
-			 * Note: this is a bit shaky for opclasses that have pseudotype
-			 * input types such as ANYARRAY or RECORD.  Currently, the
-			 * typoutput functions associated with the pseudotypes will work
-			 * okay, but we might have to try harder in future.
-			 */
-			getTypeOutputInfo(indexRelation->rd_opcintype[i],
-							  &foutoid, &typisvarlena);
-			val = OidOutputFunctionCall(foutoid, values[i]);
+			}
 		}
 
 		if (i > 0)
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 6932289..175714d 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -86,11 +86,11 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 		Datum		arg;
 		bool		null;
 		int			flags;
-
 		/*
 		 * We can use the cached (default) support procs since no cross-type
 		 * comparison can be needed.
 		 */
+		//elog(NOTICE, "_bt_mkscankey i %d", i);
 		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		arg = index_getattr(itup, i + 1, itupdesc, &null);
 		flags = (null ? SK_ISNULL : 0) | (indoption[i] << SK_BT_INDOPTION_SHIFT);
@@ -127,11 +127,12 @@ _bt_mkscankey_nodata(Relation rel)
 	int			i;
 
 	natts = RelationGetNumberOfAttributes(rel);
+	int		nkeyatts = rel->rd_index->indnkeyatts;
 	indoption = rel->rd_indoption;
 
 	skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
 
-	for (i = 0; i < natts; i++)
+	for (i = 0; i < nkeyatts; i++)
 	{
 		FmgrInfo   *procinfo;
 		int			flags;
@@ -140,6 +141,7 @@ _bt_mkscankey_nodata(Relation rel)
 		 * We can use the cached (default) support procs since no cross-type
 		 * comparison can be needed.
 		 */
+		//elog(NOTICE, "_bt_mkscankey_nodata i %d", i);
 		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		flags = SK_ISNULL | (indoption[i] << SK_BT_INDOPTION_SHIFT);
 		ScanKeyEntryInitializeWithInfo(&skey[i],
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 27a12a0..4ba362b 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -424,38 +424,44 @@ ConstructTupleDescriptor(Relation heapRelation,
 			elog(ERROR, "too few entries in colnames list");
 		namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
 		colnames_item = lnext(colnames_item);
-
-		/*
-		 * Check the opclass and index AM to see if either provides a keytype
-		 * (overriding the attribute type).  Opclass takes precedence.
-		 */
-		tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
-		if (!HeapTupleIsValid(tuple))
-			elog(ERROR, "cache lookup failed for opclass %u",
-				 classObjectId[i]);
-		opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
-		if (OidIsValid(opclassTup->opckeytype))
-			keyType = opclassTup->opckeytype;
-		else
-			keyType = amform->amkeytype;
-		ReleaseSysCache(tuple);
-
-		if (OidIsValid(keyType) && keyType != to->atttypid)
+		if (i < indexInfo->ii_NumIndexKeyAttrs)
 		{
-			/* index value and heap value have different types */
-			tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+			/*
+			* Check the opclass and index AM to see if either provides a keytype
+			* (overriding the attribute type).  Opclass takes precedence.
+			*/
+			tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
 			if (!HeapTupleIsValid(tuple))
-				elog(ERROR, "cache lookup failed for type %u", keyType);
-			typeTup = (Form_pg_type) GETSTRUCT(tuple);
-
-			to->atttypid = keyType;
-			to->atttypmod = -1;
-			to->attlen = typeTup->typlen;
-			to->attbyval = typeTup->typbyval;
-			to->attalign = typeTup->typalign;
-			to->attstorage = typeTup->typstorage;
-
+				elog(ERROR, "cache lookup failed for opclass %u",
+					classObjectId[i]);
+			opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
+			if (OidIsValid(opclassTup->opckeytype))
+				keyType = opclassTup->opckeytype;
+			else
+				keyType = amform->amkeytype;
 			ReleaseSysCache(tuple);
+
+			if (OidIsValid(keyType) && keyType != to->atttypid)
+			{
+				/* index value and heap value have different types */
+				tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+				if (!HeapTupleIsValid(tuple))
+					elog(ERROR, "cache lookup failed for type %u", keyType);
+				typeTup = (Form_pg_type) GETSTRUCT(tuple);
+
+				to->atttypid = keyType;
+				to->atttypmod = -1;
+				to->attlen = typeTup->typlen;
+				to->attbyval = typeTup->typbyval;
+				to->attalign = typeTup->typalign;
+				to->attstorage = typeTup->typstorage;
+
+				ReleaseSysCache(tuple);
+			}
+		}
+		else
+		{
+			//elog(NOTICE, "ConstructTupleDescriptor. Included opclass attr num %d. Don't check opclass", i);
 		}
 	}
 
@@ -500,7 +506,6 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
 	pg_attribute = heap_open(AttributeRelationId, RowExclusiveLock);
 
 	indstate = CatalogOpenIndexes(pg_attribute);
-
 	/*
 	 * insert data from new index's tupdesc into pg_attribute
 	 */
@@ -866,7 +871,6 @@ index_create(Relation heapRelation,
 	indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
 	indexRelation->rd_rel->relam = accessMethodObjectId;
 	indexRelation->rd_rel->relhasoids = false;
-
 	/*
 	 * store index's pg_class entry
 	 */
@@ -998,7 +1002,7 @@ index_create(Relation heapRelation,
 
 		/* Store dependency on collations */
 		/* The default collation is pinned, so don't bother recording it */
-		for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+		for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
 		{
 			if (OidIsValid(collationObjectId[i]) &&
 				collationObjectId[i] != DEFAULT_COLLATION_OID)
@@ -1012,7 +1016,7 @@ index_create(Relation heapRelation,
 		}
 
 		/* Store dependency on operator classes */
-		for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+		for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
 		{
 			referenced.classId = OperatorClassRelationId;
 			referenced.objectId = classObjectId[i];
@@ -1700,7 +1704,7 @@ BuildIndexInfo(Relation index)
 void
 BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
 {
-	int			ncols = index->rd_rel->relnatts;
+	int			nkeycols = IndexRelationGetNumberOfKeyAttributes(index);
 	int			i;
 
 	/*
@@ -1711,16 +1715,16 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
 	if (index->rd_rel->relam != BTREE_AM_OID)
 		elog(ERROR, "unexpected non-btree speculative unique index");
 
-	ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * ncols);
-	ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * ncols);
-	ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
+	ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
 
 	/*
 	 * We have to look up the operator's strategy number.  This provides a
 	 * cross-check that the operator does match the index.
 	 */
 	/* We need the func OIDs and strategy numbers too */
-	for (i = 0; i < ncols; i++)
+	for (i = 0; i < nkeycols; i++)
 	{
 		ii->ii_UniqueStrats[i] = BTEqualStrategyNumber;
 		ii->ii_UniqueOps[i] =
@@ -2644,7 +2648,6 @@ IndexCheckExclusion(Relation heapRelation,
 	EState	   *estate;
 	ExprContext *econtext;
 	Snapshot	snapshot;
-
 	/*
 	 * If we are reindexing the target index, mark it as no longer being
 	 * reindexed, to forestall an Assert in index_beginscan when we try to use
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 4e23dbe..aa4e430 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -983,16 +983,14 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 	ListCell   *nextExclOp;
 	ListCell   *lc;
 	int			attn;
-
+	int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
 	/* Allocate space for exclusion operator info, if needed */
 	if (exclusionOpNames)
 	{
-		int			ncols = list_length(attList);
-
-		Assert(list_length(exclusionOpNames) == ncols);
-		indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * ncols);
-		indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * ncols);
-		indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
+		Assert(list_length(exclusionOpNames) == nkeycols);
+		indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
+		indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+		indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
 		nextExclOp = list_head(exclusionOpNames);
 	}
 	else
@@ -1125,110 +1123,117 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 		/*
 		 * Identify the opclass to use.
 		 */
-		classOidP[attn] = GetIndexOpClass(attribute->opclass,
-										  atttype,
-										  accessMethodName,
-										  accessMethodId);
-
-		/*
-		 * Identify the exclusion operator, if any.
-		 */
-		if (nextExclOp)
+		if (attn < nkeycols)
 		{
-			List	   *opname = (List *) lfirst(nextExclOp);
-			Oid			opid;
-			Oid			opfamily;
-			int			strat;
+			//elog(NOTICE, "ComputeIndexAttrs attn %d, nkeycolss %d", attn, nkeycols);
+			classOidP[attn] = GetIndexOpClass(attribute->opclass,
+											atttype,
+											accessMethodName,
+											accessMethodId);
 
 			/*
-			 * Find the operator --- it must accept the column datatype
-			 * without runtime coercion (but binary compatibility is OK)
-			 */
-			opid = compatible_oper_opid(opname, atttype, atttype, false);
+			* Identify the exclusion operator, if any.
+			*/
+			if (nextExclOp)
+			{
+				List	   *opname = (List *) lfirst(nextExclOp);
+				Oid			opid;
+				Oid			opfamily;
+				int			strat;
 
-			/*
-			 * Only allow commutative operators to be used in exclusion
-			 * constraints. If X conflicts with Y, but Y does not conflict
-			 * with X, bad things will happen.
-			 */
-			if (get_commutator(opid) != opid)
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("operator %s is not commutative",
-								format_operator(opid)),
-						 errdetail("Only commutative operators can be used in exclusion constraints.")));
+				/*
+				* Find the operator --- it must accept the column datatype
+				* without runtime coercion (but binary compatibility is OK)
+				*/
+				opid = compatible_oper_opid(opname, atttype, atttype, false);
 
-			/*
-			 * Operator must be a member of the right opfamily, too
-			 */
-			opfamily = get_opclass_family(classOidP[attn]);
-			strat = get_op_opfamily_strategy(opid, opfamily);
-			if (strat == 0)
-			{
-				HeapTuple	opftuple;
-				Form_pg_opfamily opfform;
+				/*
+				* Only allow commutative operators to be used in exclusion
+				* constraints. If X conflicts with Y, but Y does not conflict
+				* with X, bad things will happen.
+				*/
+				if (get_commutator(opid) != opid)
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							errmsg("operator %s is not commutative",
+									format_operator(opid)),
+							errdetail("Only commutative operators can be used in exclusion constraints.")));
 
 				/*
-				 * attribute->opclass might not explicitly name the opfamily,
-				 * so fetch the name of the selected opfamily for use in the
-				 * error message.
-				 */
-				opftuple = SearchSysCache1(OPFAMILYOID,
-										   ObjectIdGetDatum(opfamily));
-				if (!HeapTupleIsValid(opftuple))
-					elog(ERROR, "cache lookup failed for opfamily %u",
-						 opfamily);
-				opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
+				* Operator must be a member of the right opfamily, too
+				*/
+				opfamily = get_opclass_family(classOidP[attn]);
+				strat = get_op_opfamily_strategy(opid, opfamily);
+				if (strat == 0)
+				{
+					HeapTuple	opftuple;
+					Form_pg_opfamily opfform;
+
+					/*
+					* attribute->opclass might not explicitly name the opfamily,
+					* so fetch the name of the selected opfamily for use in the
+					* error message.
+					*/
+					opftuple = SearchSysCache1(OPFAMILYOID,
+											ObjectIdGetDatum(opfamily));
+					if (!HeapTupleIsValid(opftuple))
+						elog(ERROR, "cache lookup failed for opfamily %u",
+							opfamily);
+					opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
 
-				ereport(ERROR,
-						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-						 errmsg("operator %s is not a member of operator family \"%s\"",
-								format_operator(opid),
-								NameStr(opfform->opfname)),
-						 errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
-			}
+					ereport(ERROR,
+							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+							errmsg("operator %s is not a member of operator family \"%s\"",
+									format_operator(opid),
+									NameStr(opfform->opfname)),
+							errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
+				}
 
-			indexInfo->ii_ExclusionOps[attn] = opid;
-			indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
-			indexInfo->ii_ExclusionStrats[attn] = strat;
-			nextExclOp = lnext(nextExclOp);
-		}
+				indexInfo->ii_ExclusionOps[attn] = opid;
+				indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
+				indexInfo->ii_ExclusionStrats[attn] = strat;
+				nextExclOp = lnext(nextExclOp);
+			}
 
-		/*
-		 * Set up the per-column options (indoption field).  For now, this is
-		 * zero for any un-ordered index, while ordered indexes have DESC and
-		 * NULLS FIRST/LAST options.
-		 */
-		colOptionP[attn] = 0;
-		if (amcanorder)
-		{
-			/* default ordering is ASC */
-			if (attribute->ordering == SORTBY_DESC)
-				colOptionP[attn] |= INDOPTION_DESC;
-			/* default null ordering is LAST for ASC, FIRST for DESC */
-			if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
+			/*
+			* Set up the per-column options (indoption field).  For now, this is
+			* zero for any un-ordered index, while ordered indexes have DESC and
+			* NULLS FIRST/LAST options.
+			*/
+			colOptionP[attn] = 0;
+			if (amcanorder)
 			{
+				/* default ordering is ASC */
 				if (attribute->ordering == SORTBY_DESC)
+					colOptionP[attn] |= INDOPTION_DESC;
+				/* default null ordering is LAST for ASC, FIRST for DESC */
+				if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
+				{
+					if (attribute->ordering == SORTBY_DESC)
+						colOptionP[attn] |= INDOPTION_NULLS_FIRST;
+				}
+				else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
 					colOptionP[attn] |= INDOPTION_NULLS_FIRST;
 			}
-			else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
-				colOptionP[attn] |= INDOPTION_NULLS_FIRST;
+			else
+			{
+				/* index AM does not support ordering */
+				if (attribute->ordering != SORTBY_DEFAULT)
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							errmsg("access method \"%s\" does not support ASC/DESC options",
+									accessMethodName)));
+				if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
+									accessMethodName)));
+			}
 		}
 		else
 		{
-			/* index AM does not support ordering */
-			if (attribute->ordering != SORTBY_DEFAULT)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("access method \"%s\" does not support ASC/DESC options",
-								accessMethodName)));
-			if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						 errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
-								accessMethodName)));
+			//elog(NOTICE, "ComputeIndexAttrs. Included attn %d.  Don't look for opclass", attn);
 		}
-
 		attn++;
 	}
 }
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 603d11d..ffb63f2 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -225,18 +225,22 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 			 * each indexed column must have an opclass.
 			 */
 			info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
-			info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns);
-			info->opfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
-			info->opcintype = (Oid *) palloc(sizeof(Oid) * ncolumns);
+			info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
+			info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
+			info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
 			info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
 
 			for (i = 0; i < ncolumns; i++)
 			{
 				info->indexkeys[i] = index->indkey.values[i];
+				info->canreturn[i] = index_can_return(indexRelation, i + 1);
+			}
+
+			for (i = 0; i < nkeycolumns; i++)
+			{
 				info->indexcollations[i] = indexRelation->rd_indcollation[i];
 				info->opfamily[i] = indexRelation->rd_opfamily[i];
 				info->opcintype[i] = indexRelation->rd_opcintype[i];
-				info->canreturn[i] = index_can_return(indexRelation, i + 1);
 			}
 
 			info->relam = indexRelation->rd_rel->relam;
@@ -263,7 +267,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
 				info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
 
-				for (i = 0; i < ncolumns; i++)
+				for (i = 0; i < nkeycolumns; i++)
 				{
 					int16		opt = indexRelation->rd_indoption[i];
 
@@ -291,7 +295,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
 				info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
 
-				for (i = 0; i < ncolumns; i++)
+				for (i = 0; i < nkeycolumns; i++)
 				{
 					int16		opt = indexRelation->rd_indoption[i];
 					Oid			ltopr;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 513fa57..ac828b5 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1178,7 +1178,7 @@ RelationInitIndexAccessInfo(Relation relation)
 	int2vector *indoption;
 	MemoryContext indexcxt;
 	MemoryContext oldcontext;
-	int			natts;
+	int			natts, nkeyatts;
 	uint16		amsupport;
 
 	/*
@@ -1214,6 +1214,7 @@ RelationInitIndexAccessInfo(Relation relation)
 		elog(ERROR, "relnatts disagrees with indnatts for index %u",
 			 RelationGetRelid(relation));
 	amsupport = aform->amsupport;
+	nkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
 
 	/*
 	 * Make the private context to hold index access info.  The reason we need
@@ -1294,7 +1295,7 @@ RelationInitIndexAccessInfo(Relation relation)
 	 */
 	IndexSupportInitialize(indclass, relation->rd_support,
 						   relation->rd_opfamily, relation->rd_opcintype,
-						   amsupport, natts);
+						   amsupport, nkeyatts);
 
 	/*
 	 * Similarly extract indoption and copy it to the cache entry
@@ -4366,7 +4367,7 @@ RelationGetExclusionInfo(Relation indexRelation,
 						 Oid **procs,
 						 uint16 **strategies)
 {
-	int			ncols = indexRelation->rd_rel->relnatts;
+	int			nkeycols = IndexRelationGetNumberOfKeyAttributes(indexRelation);
 	Oid		   *ops;
 	Oid		   *funcs;
 	uint16	   *strats;
@@ -4379,16 +4380,16 @@ RelationGetExclusionInfo(Relation indexRelation,
 	int			i;
 
 	/* Allocate result space in caller context */
-	*operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
-	*procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
-	*strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
+	*operators = ops = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	*procs = funcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	*strategies = strats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
 
 	/* Quick exit if we have the data cached already */
 	if (indexRelation->rd_exclstrats != NULL)
 	{
-		memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
-		memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
-		memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
+		memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * nkeycols);
+		memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * nkeycols);
+		memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * nkeycols);
 		return;
 	}
 
@@ -4437,12 +4438,12 @@ RelationGetExclusionInfo(Relation indexRelation,
 		arr = DatumGetArrayTypeP(val);	/* ensure not toasted */
 		nelem = ARR_DIMS(arr)[0];
 		if (ARR_NDIM(arr) != 1 ||
-			nelem != ncols ||
+			nelem != nkeycols ||
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != OIDOID)
 			elog(ERROR, "conexclop is not a 1-D Oid array");
 
-		memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
+		memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * nkeycols);
 	}
 
 	systable_endscan(conscan);
@@ -4453,7 +4454,7 @@ RelationGetExclusionInfo(Relation indexRelation,
 			 RelationGetRelationName(indexRelation));
 
 	/* We need the func OIDs and strategy numbers too */
-	for (i = 0; i < ncols; i++)
+	for (i = 0; i < nkeycols; i++)
 	{
 		funcs[i] = get_opcode(ops[i]);
 		strats[i] = get_op_opfamily_strategy(ops[i],
@@ -4466,12 +4467,12 @@ RelationGetExclusionInfo(Relation indexRelation,
 
 	/* Save a copy of the results in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
-	indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
-	indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
-	indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
-	memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
-	memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
-	memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
+	indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+	indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
+	memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * nkeycols);
+	memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * nkeycols);
+	memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * nkeycols);
 	MemoryContextSwitchTo(oldcxt);
 }
 
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index d532e87..ec2a49c 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -810,9 +810,8 @@ tuplesort_begin_index_btree(Relation heapRel,
 	state->heapRel = heapRel;
 	state->indexRel = indexRel;
 	state->enforceUnique = enforceUnique;
-
 	indexScanKey = _bt_mkscankey_nodata(indexRel);
-	state->nKeys = RelationGetNumberOfAttributes(indexRel);
+	state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
 
 	/* Prepare SortSupport data for each column */
 	state->sortKeys = (SortSupport) palloc0(state->nKeys *

