/*-------------------------------------------------------------------------
 *
 * indexing.c
 *	  This file contains routines to support indices defined on system
 *	  catalogs.
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.53 1999/11/25 00:15:56 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_index.h"
#include "miscadmin.h"
#include "utils/syscache.h"

/*
 * Names of indices - they match all system caches
 */

char	   *Name_pg_aggregate_indices[Num_pg_aggregate_indices] =
			{AggregateNameTypeIndex};
char	   *Name_pg_am_indices[Num_pg_am_indices] =
			{AmNameIndex};
char	   *Name_pg_amop_indices[Num_pg_amop_indices] =
		 	{AccessMethodOpidIndex, AccessMethodStrategyIndex};
char	   *Name_pg_attr_indices[Num_pg_attr_indices] =
		 	{AttributeRelidNameIndex, AttributeRelidNumIndex};
char	   *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
		 	{AttrDefaultIndex};
char	   *Name_pg_class_indices[Num_pg_class_indices] =
		 	{ClassNameIndex, ClassOidIndex};
char	   *Name_pg_group_indices[Num_pg_group_indices] =
		 	{GroupNameIndex, GroupSysidIndex};
char	   *Name_pg_index_indices[Num_pg_index_indices] =
		 	{IndexRelidIndex};
char	   *Name_pg_inherits_indices[Num_pg_inherits_indices] =
		 	{InheritsRelidSeqnoIndex};
char	   *Name_pg_language_indices[Num_pg_language_indices] =
		 	{LanguageOidIndex, LanguageNameIndex};
char	   *Name_pg_listener_indices[Num_pg_listener_indices] =
		 	{ListenerRelnamePidIndex};
char	   *Name_pg_opclass_indices[Num_pg_opclass_indices] =
		 	{OpclassNameIndex, OpclassDeftypeIndex};
char	   *Name_pg_operator_indices[Num_pg_operator_indices] =
		 	{OperatorOidIndex, OperatorNameIndex};
char	   *Name_pg_proc_indices[Num_pg_proc_indices] =
		 	{ProcedureOidIndex, ProcedureNameIndex};
char	   *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
		 	{RelCheckIndex};
char	   *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =
		 	{RewriteOidIndex, RewriteRulenameIndex};
char	   *Name_pg_shadow_indices[Num_pg_shadow_indices] =
		 	{ShadowNameIndex, ShadowSysidIndex};
char	   *Name_pg_statistic_indices[Num_pg_statistic_indices] =
		 	{StatisticRelidAttnumOpIndex};
char	   *Name_pg_trigger_indices[Num_pg_trigger_indices] =
		 	{TriggerRelidIndex,	TriggerConstrNameIndex, TriggerConstrRelidIndex};
char	   *Name_pg_type_indices[Num_pg_type_indices] =
		 	{TypeNameIndex, TypeOidIndex};
char       *Name_pg_description_indices[Num_pg_description_indices] =
		 	{DescriptionObjIndex};



static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
										   Relation idesc,
										   ScanKey skey,
										   int16 num_keys);


/*
 * Changes (appends) to catalogs can (and does) happen at various places
 * throughout the code.  We need a generic routine that will open all of
 * the indices defined on a given catalog a return the relation descriptors
 * associated with them.
 */
void
CatalogOpenIndices(int nIndices, char **names, Relation *idescs)
{
	int			i;

	for (i = 0; i < nIndices; i++)
		idescs[i] = index_openr(names[i]);
}

/*
 * This is the inverse routine to CatalogOpenIndices()
 */
void
CatalogCloseIndices(int nIndices, Relation *idescs)
{
	int			i;

	for (i = 0; i < nIndices; i++)
		index_close(idescs[i]);
}


/*
 * For the same reasons outlined above CatalogOpenIndices() we need a routine
 * that takes a new catalog tuple and inserts an associated index tuple into
 * each catalog index.
 */
void
CatalogIndexInsert(Relation *idescs,
				   int nIndices,
				   Relation heapRelation,
				   HeapTuple heapTuple)
{
	HeapTuple	index_tup;
	TupleDesc	heapDescriptor;
	Form_pg_index index_form;
	Datum		datum[INDEX_MAX_KEYS];
	char		nulls[INDEX_MAX_KEYS];
	int			natts;
	AttrNumber *attnumP;
	FuncIndexInfo finfo,
			   *finfoP;
	int			i;

	heapDescriptor = RelationGetDescr(heapRelation);

	for (i = 0; i < nIndices; i++)
	{
		InsertIndexResult indexRes;

		index_tup = SearchSysCacheTupleCopy(INDEXRELID,
									  ObjectIdGetDatum(idescs[i]->rd_id),
											0, 0, 0);
		Assert(index_tup);
		index_form = (Form_pg_index) GETSTRUCT(index_tup);

		if (index_form->indproc != InvalidOid)
		{
			int			fatts;

			/*
			 * Compute the number of attributes we are indexing upon.
			 */
			for (attnumP = index_form->indkey, fatts = 0;
				 fatts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber;
				 attnumP++, fatts++)
				;
			FIgetnArgs(&finfo) = fatts;
			natts = 1;
			FIgetProcOid(&finfo) = index_form->indproc;
			*(FIgetname(&finfo)) = '\0';
			finfoP = &finfo;
		}
		else
		{
			natts = RelationGetDescr(idescs[i])->natts;
			finfoP = (FuncIndexInfo *) NULL;
		}

		FormIndexDatum(natts,
					   (AttrNumber *) index_form->indkey,
					   heapTuple,
					   heapDescriptor,
					   datum,
					   nulls,
					   finfoP);

		indexRes = index_insert(idescs[i], datum, nulls,
								&heapTuple->t_self, heapRelation);
		if (indexRes)
			pfree(indexRes);

		pfree(index_tup);
	}
}

/*
 * This is needed at initialization when reldescs for some of the crucial
 * system catalogs are created and nailed into the cache.
 */
bool
CatalogHasIndex(char *catName, Oid catId)
{
	Relation	pg_class;
	HeapTuple	htup;
	Form_pg_class pgRelP;
	int			i;

	Assert(IsSystemRelationName(catName));

	/*
	 * If we're bootstraping we don't have pg_class (or any indices).
	 */
	if (IsBootstrapProcessingMode())
		return false;

	if (IsInitProcessingMode())
	{
		for (i = 0; IndexedCatalogNames[i] != NULL; i++)
		{
			if (strcmp(IndexedCatalogNames[i], catName) == 0)
				return true;
		}
		return false;
	}

	pg_class = heap_openr(RelationRelationName, AccessShareLock);
	htup = ClassOidIndexScan(pg_class, catId);
	heap_close(pg_class, AccessShareLock);

	if (!HeapTupleIsValid(htup))
	{
		elog(NOTICE, "CatalogHasIndex: no relation with oid %u", catId);
		return false;
	}

	pgRelP = (Form_pg_class) GETSTRUCT(htup);
	return pgRelP->relhasindex;
}


/*
 *	CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
 *								from a catalog relation.
 *
 *		Since the index may contain pointers to dead tuples, we need to
 *		iterate until we find a tuple that's valid and satisfies the scan
 *		key.
 */
static HeapTuple
CatalogIndexFetchTuple(Relation heapRelation,
					   Relation idesc,
					   ScanKey skey,
					   int16 num_keys)
{
	IndexScanDesc sd;
	RetrieveIndexResult indexRes;
	HeapTupleData tuple;
	HeapTuple	result = NULL;
	Buffer		buffer;

	sd = index_beginscan(idesc, false, num_keys, skey);
	tuple.t_data = NULL;
	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
	{
		tuple.t_self = indexRes->heap_iptr;
		heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer);
		pfree(indexRes);
		if (tuple.t_data != NULL)
			break;
	}

	if (tuple.t_data != NULL)
	{
		result = heap_copytuple(&tuple);
		ReleaseBuffer(buffer);
	}

	index_endscan(sd);
	pfree(sd);
	return result;
}


/*---------------------------------------------------------------------
 *                       Class-specific index lookups
 *---------------------------------------------------------------------
 */

/*
 * The remainder of the file is for individual index scan routines.  Each
 * index should be scanned according to how it was defined during bootstrap
 * (that is, functional or normal) and what arguments the cache lookup
 * requires.  Each routine returns the heap tuple that qualifies.
 */


HeapTuple
AggregateNameTypeIndexScan(Relation heapRelation, char *aggName, Oid aggType)
{
	Relation	idesc;
	ScanKeyData skey[2];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(aggName));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(aggType));

	idesc = index_openr(AggregateNameTypeIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);

	index_close(idesc);
	return tuple;
}


HeapTuple
AmNameIndexScan(Relation heapRelation, char *amName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(amName));

	idesc = index_openr(AmNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
AccessMethodOpidIndexScan(Relation heapRelation,
						  Oid claid,
						  Oid opopr,
						  Oid opid)
{
	Relation	idesc;
	ScanKeyData skey[3];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(claid));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(opopr));

	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(opid));

	idesc = index_openr(AccessMethodOpidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);

	index_close(idesc);

	return tuple;
}

HeapTuple
AccessMethodStrategyIndexScan(Relation heapRelation,
							  Oid opid,
							  Oid claid,
							  int2 opstrategy)
{
	Relation	idesc;
	ScanKeyData skey[3];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(opid));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(claid));

	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_INT2EQ,
						   Int16GetDatum(opstrategy));

	idesc = index_openr(AccessMethodStrategyIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);

	index_close(idesc);

	return tuple;
}


HeapTuple
AttributeRelidNameIndexScan(Relation heapRelation,
					   Oid relid,
					   char *attname)
{
	Relation	idesc;
	ScanKeyData skey[2];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relid));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_NAMEEQ,
						   NameGetDatum(attname));

	idesc = index_openr(AttributeRelidNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);

	index_close(idesc);

	return tuple;
}


HeapTuple
AttributeRelidNumIndexScan(Relation heapRelation,
					  Oid relid,
					  AttrNumber attnum)
{
	Relation	idesc;
	ScanKeyData skey[2];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relid));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT2EQ,
						   Int16GetDatum(attnum));

	idesc = index_openr(AttributeRelidNumIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);

	index_close(idesc);

	return tuple;
}


HeapTuple
OpclassDeftypeIndexScan(Relation heapRelation, Oid defType)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(defType));

	idesc = index_openr(OpclassDeftypeIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
OpclassNameIndexScan(Relation heapRelation, char *opcName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(opcName));

	idesc = index_openr(OpclassNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
GroupNameIndexScan(Relation heapRelation, char *groName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(groName));

	idesc = index_openr(GroupNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
GroupSysidIndexScan(Relation heapRelation, int4 sysId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_INT4EQ,
						   Int32GetDatum(sysId));

	idesc = index_openr(GroupSysidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
IndexRelidIndexScan(Relation heapRelation, Oid relid)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relid));

	idesc = index_openr(IndexRelidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
InheritsRelidSeqnoIndexScan(Relation heapRelation,
						   Oid relid,
						   int4 seqno)
{
	Relation	idesc;
	ScanKeyData skey[2];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relid));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT4EQ,
						   Int32GetDatum(seqno));

	idesc = index_openr(InheritsRelidSeqnoIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);

	index_close(idesc);

	return tuple;
}


HeapTuple
LanguageNameIndexScan(Relation heapRelation, char *lanName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(lanName));

	idesc = index_openr(LanguageNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
LanguageOidIndexScan(Relation heapRelation, Oid lanId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(lanId));

	idesc = index_openr(LanguageOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
ListenerRelnamePidIndexScan(Relation heapRelation, char *relName, int4 pid)
{
	Relation	idesc;
	ScanKeyData skey[2];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(relName));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT4EQ,
						   Int32GetDatum(pid));

	idesc = index_openr(ListenerRelnamePidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);

	index_close(idesc);
	return tuple;
}


HeapTuple
OperatorNameIndexScan(Relation heapRelation,
					   char *oprName,
					   Oid   oprLeft,
					   Oid   oprRight,
                       char  oprKind)
{
	Relation	idesc;
	ScanKeyData skey[4];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(oprName));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(oprLeft));

	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(oprRight));

	ScanKeyEntryInitialize(&skey[3],
						   (bits16) 0x0,
						   (AttrNumber) 4,
						   (RegProcedure) F_CHAREQ,
						   CharGetDatum(oprKind));

	idesc = index_openr(OperatorNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 4);

	index_close(idesc);

	return tuple;
}


HeapTuple
OperatorOidIndexScan(Relation heapRelation, Oid oprId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(oprId));

	idesc = index_openr(OperatorOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
ProcedureNameIndexScan(Relation heapRelation,
					   char *procName,
					   int2 nargs,
					   Oid *argTypes)
{
	Relation	idesc;
	ScanKeyData skey[3];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(procName));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT2EQ,
						   Int16GetDatum(nargs));

	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_OID8EQ,
						   PointerGetDatum(argTypes));

	idesc = index_openr(ProcedureNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);

	index_close(idesc);

	return tuple;
}


HeapTuple
ProcedureOidIndexScan(Relation heapRelation, Oid procId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(procId));

	idesc = index_openr(ProcedureOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
ClassNameIndexScan(Relation heapRelation, char *relName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(relName));

	idesc = index_openr(ClassNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
ClassOidIndexScan(Relation heapRelation, Oid relId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relId));

	idesc = index_openr(ClassOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
RewriteRulenameIndexScan(Relation heapRelation, char *ruleName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(ruleName));

	idesc = index_openr(RewriteRulenameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
RewriteOidIndexScan(Relation heapRelation, Oid rewriteId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(rewriteId));

	idesc = index_openr(RewriteOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
ShadowNameIndexScan(Relation heapRelation, char *useName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(useName));

	idesc = index_openr(ShadowNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
ShadowSysidIndexScan(Relation heapRelation, int4 sysId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;
	
	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_INT4EQ,
						   Int32GetDatum(sysId));

	idesc = index_openr(ShadowSysidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);
	return tuple;
}


HeapTuple
StatisticRelidAttnumOpIndexScan(Relation heapRelation,
					   Oid relId,
					   AttrNumber attNum,
					   Oid op)
{
	Relation	idesc;
	ScanKeyData skey[3];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(relId));

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT2EQ,
						   Int16GetDatum(attNum));

	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(op));

	idesc = index_openr(StatisticRelidAttnumOpIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);

	index_close(idesc);

	return tuple;
}


HeapTuple
TypeNameIndexScan(Relation heapRelation, char *typeName)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_NAMEEQ,
						   PointerGetDatum(typeName));

	idesc = index_openr(TypeNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}


HeapTuple
TypeOidIndexScan(Relation heapRelation, Oid typeId)
{
	Relation	idesc;
	ScanKeyData skey[1];
	HeapTuple	tuple;

	ScanKeyEntryInitialize(&skey[0],
						   (bits16) 0x0,
						   (AttrNumber) 1,
						   (RegProcedure) F_OIDEQ,
						   ObjectIdGetDatum(typeId));

	idesc = index_openr(TypeOidIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);

	index_close(idesc);

	return tuple;
}

