📄 index.c
字号:
/*------------------------------------------------------------------------- * * index.c * code to create and destroy POSTGRES index relations * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/index.c,v 1.81.2.1 1999/08/02 05:56:54 scrappy Exp $ * * * INTERFACE ROUTINES * index_create() - Create a cataloged index relation * index_destroy() - Removes index relation from catalogs * * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "access/istrat.h"#include "bootstrap/bootstrap.h"#include "catalog/catname.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/indexing.h"#include "catalog/pg_index.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_func.h"#include "storage/smgr.h"#include "utils/builtins.h"#include "utils/relcache.h"#include "utils/syscache.h"#include "utils/temprel.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 Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp);static TupleDesc BuildFuncTupleDesc(FuncIndexInfo *funcInfo);static TupleDesc ConstructTupleDescriptor(Oid heapoid, Relation heapRelation, List *attributeList, int numatts, AttrNumber *attNums);static void ConstructIndexReldesc(Relation indexRelation, Oid amoid);static Oid UpdateRelationRelation(Relation indexRelation, char *temp_relname);static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid);static void AppendAttributeTuples(Relation indexRelation, int numatts);static void UpdateIndexRelation(Oid indexoid, Oid heapoid, FuncIndexInfo *funcInfo, int natts, AttrNumber *attNums, Oid *classOids, Node *predicate, List *attributeList, bool islossy, bool unique, bool primary);static void DefaultBuild(Relation heapRelation, Relation indexRelation, int numberOfAttributes, AttrNumber *attributeNumber, IndexStrategy indexStrategy, uint16 parameterCount, Datum *parameter, FuncIndexInfoPtr funcInfo, PredInfo *predInfo);/* ---------------------------------------------------------------- * sysatts is a structure containing attribute tuple forms * for system attributes (numbered -1, -2, ...). This really * should be generated or eliminated or moved elsewhere. -cim 1/19/91 * * typedef struct FormData_pg_attribute { * Oid attrelid; * NameData attname; * Oid atttypid; * uint32 attnvals; * int16 attlen; * AttrNumber attnum; * uint32 attnelems; * int32 attcacheoff; * int32 atttypmod; * bool attbyval; * bool attisset; * char attalign; * bool attnotnull; * bool atthasdef; * } FormData_pg_attribute; * * ---------------------------------------------------------------- */static FormData_pg_attribute sysatts[] = { {0, {"ctid"}, TIDOID, 0, 6, -1, 0, -1, -1, '\0', '\0', 'i', '\0', '\0'}, {0, {"oid"}, OIDOID, 0, 4, -2, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'}, {0, {"xmin"}, XIDOID, 0, 4, -3, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'}, {0, {"cmin"}, CIDOID, 0, 4, -4, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'}, {0, {"xmax"}, XIDOID, 0, 4, -5, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'}, {0, {"cmax"}, CIDOID, 0, 4, -6, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'},};/* ---------------------------------------------------------------- * GetHeapRelationOid * ---------------------------------------------------------------- */static OidGetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp){ Oid indoid; Oid heapoid; indoid = RelnameFindRelid(indexRelationName); if ((!istemp && OidIsValid(indoid)) || (istemp && get_temp_rel_by_name(indexRelationName) != NULL)) elog(ERROR, "Cannot create index: '%s' already exists", indexRelationName); heapoid = RelnameFindRelid(heapRelationName); if (!OidIsValid(heapoid)) elog(ERROR, "Cannot create index on '%s': relation does not exist", heapRelationName); return heapoid;}static TupleDescBuildFuncTupleDesc(FuncIndexInfo *funcInfo){ HeapTuple tuple; TupleDesc funcTupDesc; Oid retType; char *funcname; int4 nargs; Oid *argtypes; /* * Allocate and zero a tuple descriptor. */ funcTupDesc = CreateTemplateTupleDesc(1); funcTupDesc->attrs[0] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE); /* * Lookup the function for the return type. */ funcname = FIgetname(funcInfo); nargs = FIgetnArgs(funcInfo); argtypes = FIgetArglist(funcInfo); tuple = SearchSysCacheTuple(PRONAME, PointerGetDatum(funcname), Int32GetDatum(nargs), PointerGetDatum(argtypes), 0); if (!HeapTupleIsValid(tuple)) func_error("BuildFuncTupleDesc", funcname, nargs, argtypes, NULL); retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; /* * Look up the return type in pg_type for the type length. */ tuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(retType), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "Function %s return type does not exist", FIgetname(funcInfo)); /* * Assign some of the attributes values. Leave the rest as 0. */ funcTupDesc->attrs[0]->attlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen; funcTupDesc->attrs[0]->atttypid = retType; funcTupDesc->attrs[0]->attnum = 1; funcTupDesc->attrs[0]->attbyval = ((Form_pg_type) GETSTRUCT(tuple))->typbyval; funcTupDesc->attrs[0]->attcacheoff = -1; funcTupDesc->attrs[0]->atttypmod = -1; funcTupDesc->attrs[0]->attalign = ((Form_pg_type) GETSTRUCT(tuple))->typalign; /* * make the attributes name the same as the functions */ namestrcpy(&funcTupDesc->attrs[0]->attname, funcname); return funcTupDesc;}/* ---------------------------------------------------------------- * ConstructTupleDescriptor * ---------------------------------------------------------------- */static TupleDescConstructTupleDescriptor(Oid heapoid, Relation heapRelation, List *attributeList, int numatts, AttrNumber *attNums){ TupleDesc heapTupDesc; TupleDesc indexTupDesc; IndexElem *IndexKey; TypeName *IndexKeyType; AttrNumber atnum; /* attributeNumber[attributeOffset] */ AttrNumber atind; int natts; /* Form_pg_class->relnatts */ char *from; /* used to simplify memcpy below */ char *to; /* used to simplify memcpy below */ int i; /* ---------------- * allocate the new tuple descriptor * ---------------- */ natts = RelationGetForm(heapRelation)->relnatts; indexTupDesc = CreateTemplateTupleDesc(numatts); /* ---------------- * * ---------------- */ /* ---------------- * for each attribute we are indexing, obtain its attribute * tuple form from either the static table of system attribute * tuple forms or the relation tuple descriptor * ---------------- */ for (i = 0; i < numatts; i += 1) { /* ---------------- * get the attribute number and make sure it's valid * ---------------- */ atnum = attNums[i]; if (atnum > natts) elog(ERROR, "Cannot create index: attribute %d does not exist", atnum); if (attributeList) { IndexKey = (IndexElem *) lfirst(attributeList); IndexKeyType = IndexKey->typename; attributeList = lnext(attributeList); } else IndexKeyType = NULL; indexTupDesc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); /* ---------------- * determine which tuple descriptor to copy * ---------------- */ if (!AttrNumberIsForUserDefinedAttr(atnum)) { /* ---------------- * here we are indexing on a system attribute (-1...-12) * so we convert atnum into a usable index 0...11 so we can * use it to dereference the array sysatts[] which stores * tuple descriptor information for system attributes. * ---------------- */ if (atnum <= FirstLowInvalidHeapAttributeNumber || atnum >= 0) elog(ERROR, "Cannot create index on system attribute: attribute number out of range (%d)", atnum); atind = (-atnum) - 1; from = (char *) (&sysatts[atind]); } else { /* ---------------- * here we are indexing on a normal attribute (1...n) * ---------------- */ heapTupDesc = RelationGetDescr(heapRelation); atind = AttrNumberGetAttrOffset(atnum); from = (char *) (heapTupDesc->attrs[atind]); } /* ---------------- * now that we've determined the "from", let's copy * the tuple desc data... * ---------------- */ to = (char *) (indexTupDesc->attrs[i]); memcpy(to, from, ATTRIBUTE_TUPLE_SIZE); ((Form_pg_attribute) to)->attnum = i + 1; ((Form_pg_attribute) to)->attnotnull = false; ((Form_pg_attribute) to)->atthasdef = false; ((Form_pg_attribute) to)->attcacheoff = -1; ((Form_pg_attribute) to)->atttypmod = -1; ((Form_pg_attribute) to)->attalign = 'i'; /* * if the keytype is defined, we need to change the tuple form's * atttypid & attlen field to match that of the key's type */ if (IndexKeyType != NULL) { HeapTuple tup; tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(IndexKeyType->name), 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "create index: type '%s' undefined", IndexKeyType->name); ((Form_pg_attribute) to)->atttypid = tup->t_data->t_oid; ((Form_pg_attribute) to)->attbyval = ((Form_pg_type) GETSTRUCT(tup))->typbyval; ((Form_pg_attribute) to)->attlen = ((Form_pg_type) GETSTRUCT(tup))->typlen; ((Form_pg_attribute) to)->attalign = ((Form_pg_type) GETSTRUCT(tup))->typalign; ((Form_pg_attribute) to)->atttypmod = IndexKeyType->typmod; } /* ---------------- * now we have to drop in the proper relation descriptor * into the copied tuple form's attrelid and we should be * all set. * ---------------- */ ((Form_pg_attribute) to)->attrelid = heapoid; } return indexTupDesc;}/* ---------------------------------------------------------------- * AccessMethodObjectIdGetForm * Returns the formated access method tuple given its object identifier. * * XXX ADD INDEXING * * Note: * Assumes object identifier is valid. * ---------------------------------------------------------------- */Form_pg_amAccessMethodObjectIdGetForm(Oid accessMethodObjectId){ Relation pg_am_desc; HeapScanDesc pg_am_scan; HeapTuple pg_am_tuple; ScanKeyData key; Form_pg_am aform; /* ---------------- * form a scan key for the pg_am relation * ---------------- */ ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(accessMethodObjectId)); /* ---------------- * fetch the desired access method tuple * ---------------- */ pg_am_desc = heap_openr(AccessMethodRelationName); pg_am_scan = heap_beginscan(pg_am_desc, 0, SnapshotNow, 1, &key); pg_am_tuple = heap_getnext(pg_am_scan, 0); /* ---------------- * return NULL if not found * ---------------- */ if (!HeapTupleIsValid(pg_am_tuple)) { heap_endscan(pg_am_scan); heap_close(pg_am_desc); return NULL; } /* ---------------- * if found am tuple, then copy the form and return the copy * ---------------- */ aform = (Form_pg_am) palloc(sizeof *aform); memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform); heap_endscan(pg_am_scan); heap_close(pg_am_desc); return aform;}/* ---------------------------------------------------------------- * ConstructIndexReldesc * ---------------------------------------------------------------- */static voidConstructIndexReldesc(Relation indexRelation, Oid amoid){ extern GlobalMemory CacheCxt; MemoryContext oldcxt; /* ---------------- * here we make certain to allocate the access method * tuple within the cache context lest it vanish when the * context changes * ---------------- */ if (!CacheCxt) CacheCxt = CreateGlobalMemory("Cache"); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); indexRelation->rd_am = AccessMethodObjectIdGetForm(amoid); MemoryContextSwitchTo(oldcxt); /* ---------------- * XXX missing the initialization of some other fields
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -