📄 index.c
字号:
/*------------------------------------------------------------------------- * * 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 + -