⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 index.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
/*------------------------------------------------------------------------- * * index.c *	  code to create and destroy POSTGRES index relations * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.219 2003/09/29 00:05:24 petere Exp $ * * * INTERFACE ROUTINES *		index_create()			- Create a cataloged index relation *		index_drop()			- Removes index relation from catalogs *		BuildIndexInfo()		- Prepare to insert index tuples *		FormIndexDatum()		- Construct datum vector for one index tuple * *------------------------------------------------------------------------- */#include "postgres.h"#include <unistd.h>#include "access/genam.h"#include "access/heapam.h"#include "access/istrat.h"#include "bootstrap/bootstrap.h"#include "catalog/catalog.h"#include "catalog/catname.h"#include "catalog/dependency.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/indexing.h"#include "catalog/pg_constraint.h"#include "catalog/pg_index.h"#include "catalog/pg_opclass.h"#include "catalog/pg_proc.h"#include "catalog/pg_type.h"#include "executor/executor.h"#include "miscadmin.h"#include "optimizer/clauses.h"#include "optimizer/prep.h"#include "parser/parse_expr.h"#include "parser/parse_func.h"#include "storage/sinval.h"#include "storage/smgr.h"#include "utils/builtins.h"#include "utils/catcache.h"#include "utils/fmgroids.h"#include "utils/inval.h"#include "utils/lsyscache.h"#include "utils/relcache.h"#include "utils/syscache.h"/* * macros used in guessing how many tuples are on a page. */#define AVG_ATTR_SIZE 8#define NTUPLES_PER_PAGE(natts) \	((BLCKSZ - MAXALIGN(sizeof(PageHeaderData))) / \	((natts) * AVG_ATTR_SIZE + MAXALIGN(sizeof(HeapTupleHeaderData))))/* non-export function prototypes */static TupleDesc ConstructTupleDescriptor(Relation heapRelation,						 IndexInfo *indexInfo,						 Oid *classObjectId);static void UpdateRelationRelation(Relation indexRelation);static void InitializeAttributeOids(Relation indexRelation,						int numatts, Oid indexoid);static void AppendAttributeTuples(Relation indexRelation, int numatts);static void UpdateIndexRelation(Oid indexoid, Oid heapoid,					IndexInfo *indexInfo,					Oid *classOids,					bool primary);static Oid	IndexGetRelation(Oid indexId);/* *		ConstructTupleDescriptor * * Build an index tuple descriptor for a new index */static TupleDescConstructTupleDescriptor(Relation heapRelation,						 IndexInfo *indexInfo,						 Oid *classObjectId){	int			numatts = indexInfo->ii_NumIndexAttrs;	List	   *indexprs = indexInfo->ii_Expressions;	TupleDesc	heapTupDesc;	TupleDesc	indexTupDesc;	int			natts;			/* #atts in heap rel --- for error checks */	int			i;	heapTupDesc = RelationGetDescr(heapRelation);	natts = RelationGetForm(heapRelation)->relnatts;	/*	 * allocate the new tuple descriptor	 */	indexTupDesc = CreateTemplateTupleDesc(numatts, false);	/*	 * For simple index columns, we copy the pg_attribute row from the	 * parent relation and modify it as necessary.	For expressions we	 * have to cons up a pg_attribute row the hard way.	 */	for (i = 0; i < numatts; i++)	{		AttrNumber	atnum = indexInfo->ii_KeyAttrNumbers[i];		Form_pg_attribute to;		HeapTuple	tuple;		Form_pg_type typeTup;		Oid			keyType;		indexTupDesc->attrs[i] = to =			(Form_pg_attribute) palloc0(ATTRIBUTE_TUPLE_SIZE);		if (atnum != 0)		{			/* Simple index column */			Form_pg_attribute from;			if (atnum < 0)			{				/*				 * here we are indexing on a system attribute (-1...-n)				 */				from = SystemAttributeDefinition(atnum,									   heapRelation->rd_rel->relhasoids);			}			else			{				/*				 * here we are indexing on a normal attribute (1...n)				 */				if (atnum > natts)		/* safety check */					elog(ERROR, "invalid column number %d", atnum);				from = heapTupDesc->attrs[AttrNumberGetAttrOffset(atnum)];			}			/*			 * now that we've determined the "from", let's copy the tuple			 * desc data...			 */			memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);			/*			 * Fix the stuff that should not be the same as the underlying			 * attr			 */			to->attnum = i + 1;			to->attstattarget = 0;			to->attcacheoff = -1;			to->attnotnull = false;			to->atthasdef = false;			to->attislocal = true;			to->attinhcount = 0;		}		else		{			/* Expressional index */			Node	   *indexkey;			if (indexprs == NIL)	/* shouldn't happen */				elog(ERROR, "too few entries in indexprs list");			indexkey = (Node *) lfirst(indexprs);			indexprs = lnext(indexprs);			/*			 * Make the attribute's name "pg_expresssion_nnn" (maybe think			 * of something better later)			 */			sprintf(NameStr(to->attname), "pg_expression_%d", i + 1);			/*			 * Lookup the expression type in pg_type for the type length			 * etc.			 */			keyType = exprType(indexkey);			tuple = SearchSysCache(TYPEOID,								   ObjectIdGetDatum(keyType),								   0, 0, 0);			if (!HeapTupleIsValid(tuple))				elog(ERROR, "cache lookup failed for type %u", keyType);			typeTup = (Form_pg_type) GETSTRUCT(tuple);			/*			 * Assign some of the attributes values. Leave the rest as 0.			 */			to->attnum = i + 1;			to->atttypid = keyType;			to->attlen = typeTup->typlen;			to->attbyval = typeTup->typbyval;			to->attstorage = typeTup->typstorage;			to->attalign = typeTup->typalign;			to->attcacheoff = -1;			to->atttypmod = -1;			to->attislocal = true;			ReleaseSysCache(tuple);		}		/*		 * We do not yet have the correct relation OID for the index, so		 * just set it invalid for now.  InitializeAttributeOids() will		 * fix it later.		 */		to->attrelid = InvalidOid;		/*		 * Check the opclass to see if it provides a keytype (overriding		 * the attribute type).		 */		tuple = SearchSysCache(CLAOID,							   ObjectIdGetDatum(classObjectId[i]),							   0, 0, 0);		if (!HeapTupleIsValid(tuple))			elog(ERROR, "cache lookup failed for opclass %u",				 classObjectId[i]);		keyType = ((Form_pg_opclass) GETSTRUCT(tuple))->opckeytype;		ReleaseSysCache(tuple);		if (OidIsValid(keyType) && keyType != to->atttypid)		{			/* index value and heap value have different types */			tuple = SearchSysCache(TYPEOID,								   ObjectIdGetDatum(keyType),								   0, 0, 0);			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);		}	}	return indexTupDesc;}/* ---------------------------------------------------------------- *		UpdateRelationRelation * ---------------------------------------------------------------- */static voidUpdateRelationRelation(Relation indexRelation){	Relation	pg_class;	HeapTuple	tuple;	pg_class = heap_openr(RelationRelationName, RowExclusiveLock);	/* XXX Natts_pg_class_fixed is a hack - see pg_class.h */	tuple = heap_addheader(Natts_pg_class_fixed,						   true,						   CLASS_TUPLE_SIZE,						   (void *) indexRelation->rd_rel);	/*	 * the new tuple must have the oid already chosen for the index. sure	 * would be embarrassing to do this sort of thing in polite company.	 */	HeapTupleSetOid(tuple, RelationGetRelid(indexRelation));	simple_heap_insert(pg_class, tuple);	/* update the system catalog indexes */	CatalogUpdateIndexes(pg_class, tuple);	heap_freetuple(tuple);	heap_close(pg_class, RowExclusiveLock);}/* ---------------------------------------------------------------- *		InitializeAttributeOids * ---------------------------------------------------------------- */static voidInitializeAttributeOids(Relation indexRelation,						int numatts,						Oid indexoid){	TupleDesc	tupleDescriptor;	int			i;	tupleDescriptor = RelationGetDescr(indexRelation);	for (i = 0; i < numatts; i += 1)		tupleDescriptor->attrs[i]->attrelid = indexoid;}/* ---------------------------------------------------------------- *		AppendAttributeTuples * ---------------------------------------------------------------- */static voidAppendAttributeTuples(Relation indexRelation, int numatts){	Relation	pg_attribute;	CatalogIndexState indstate;	TupleDesc	indexTupDesc;	HeapTuple	new_tuple;	int			i;	/*	 * open the attribute relation and its indexes	 */	pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);	indstate = CatalogOpenIndexes(pg_attribute);	/*	 * insert data from new index's tupdesc into pg_attribute	 */	indexTupDesc = RelationGetDescr(indexRelation);	for (i = 0; i < numatts; i++)	{		/*		 * There used to be very grotty code here to set these fields, but		 * I think it's unnecessary.  They should be set already.		 */		Assert(indexTupDesc->attrs[i]->attnum == i + 1);		Assert(indexTupDesc->attrs[i]->attcacheoff == -1);		new_tuple = heap_addheader(Natts_pg_attribute,								   false,								   ATTRIBUTE_TUPLE_SIZE,								   (void *) indexTupDesc->attrs[i]);		simple_heap_insert(pg_attribute, new_tuple);		CatalogIndexInsert(indstate, new_tuple);		heap_freetuple(new_tuple);	}	CatalogCloseIndexes(indstate);	heap_close(pg_attribute, RowExclusiveLock);}/* ---------------------------------------------------------------- *		UpdateIndexRelation * ---------------------------------------------------------------- */static voidUpdateIndexRelation(Oid indexoid,					Oid heapoid,					IndexInfo *indexInfo,					Oid *classOids,					bool primary){	int16		indkey[INDEX_MAX_KEYS];	Oid			indclass[INDEX_MAX_KEYS];	Datum		exprsDatum;	Datum		predDatum;	Datum		values[Natts_pg_index];	char		nulls[Natts_pg_index];	Relation	pg_index;	HeapTuple	tuple;	int			i;	/*	 * Copy the index key and opclass info into zero-filled vectors	 */	MemSet(indkey, 0, sizeof(indkey));	MemSet(indclass, 0, sizeof(indclass));	for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)	{		indkey[i] = indexInfo->ii_KeyAttrNumbers[i];		indclass[i] = classOids[i];	}	/*	 * Convert the index expressions (if any) to a text datum	 */	if (indexInfo->ii_Expressions != NIL)	{		char	   *exprsString;		exprsString = nodeToString(indexInfo->ii_Expressions);		exprsDatum = DirectFunctionCall1(textin,										 CStringGetDatum(exprsString));		pfree(exprsString);	}	else		exprsDatum = (Datum) 0;	/*	 * Convert the index predicate (if any) to a text datum	 */	if (indexInfo->ii_Predicate != NIL)	{		char	   *predString;		predString = nodeToString(indexInfo->ii_Predicate);		predDatum = DirectFunctionCall1(textin,										CStringGetDatum(predString));		pfree(predString);	}	else		predDatum = (Datum) 0;	/*	 * open the system catalog index relation	 */	pg_index = heap_openr(IndexRelationName, RowExclusiveLock);	/*	 * Build a pg_index tuple	 */	MemSet(nulls, ' ', sizeof(nulls));	values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid);	values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid);	values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);	values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);	values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);	values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);	values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);	values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);	values[Anum_pg_index_indexprs - 1] = exprsDatum;	if (exprsDatum == (Datum) 0)		nulls[Anum_pg_index_indexprs - 1] = 'n';	values[Anum_pg_index_indpred - 1] = predDatum;	if (predDatum == (Datum) 0)		nulls[Anum_pg_index_indpred - 1] = 'n';	tuple = heap_formtuple(RelationGetDescr(pg_index), values, nulls);	/*	 * insert the tuple into the pg_index catalog	 */	simple_heap_insert(pg_index, tuple);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -