aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/index.c')
-rw-r--r--src/backend/catalog/index.c3019
1 files changed, 1545 insertions, 1474 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index b2071f814f2..6dd75742798 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1,25 +1,25 @@
/*-------------------------------------------------------------------------
*
* index.c--
- * code to create and destroy POSTGRES index relations
+ * code to create and destroy POSTGRES index relations
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.19 1997/08/22 14:10:26 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.20 1997/09/07 04:40:19 momjian Exp $
*
*
* INTERFACE ROUTINES
- * index_create() - Create a cataloged index relation
- * index_destroy() - Removes index relation from catalogs
+ * index_create() - Create a cataloged index relation
+ * index_destroy() - Removes index relation from catalogs
*
* NOTES
- * Much of this code uses hardcoded sequential heap relation scans
- * to fetch information from the catalogs. These should all be
- * rewritten to use the system caches lookup routines like
- * SearchSysCacheTuple, which can do efficient lookup and
- * caching.
+ * Much of this code uses hardcoded sequential heap relation scans
+ * to fetch information from the catalogs. These should all be
+ * rewritten to use the system caches lookup routines like
+ * SearchSysCacheTuple, which can do efficient lookup and
+ * caching.
*
*-------------------------------------------------------------------------
*/
@@ -51,9 +51,9 @@
#include <access/istrat.h>
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
/*
@@ -63,70 +63,75 @@
#define NTUPLES_PER_PAGE(natts) (BLCKSZ/((natts)*AVG_TUPLE_SIZE))
/* non-export function prototypes */
-static Oid RelationNameGetObjectId(char *relationName, Relation pg_class,
- bool setHasIndexAttribute);
-static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName);
-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);
-static void InitializeAttributeOids(Relation indexRelation,
- int numatts,
- Oid indexoid);
+static Oid
+RelationNameGetObjectId(char *relationName, Relation pg_class,
+ bool setHasIndexAttribute);
+static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName);
+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);
+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);
-static void DefaultBuild(Relation heapRelation, Relation indexRelation,
- int numberOfAttributes, AttrNumber attributeNumber[],
- IndexStrategy indexStrategy, uint16 parameterCount,
- Datum parameter[], FuncIndexInfoPtr funcInfo, PredInfo *predInfo);
+ 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);
+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
+ * 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;
- * bool attbyval;
- * bool attisset;
- * char attalign;
- * bool attnotnull;
- * bool atthasdef;
+ * Oid attrelid;
+ * NameData attname;
+ * Oid atttypid;
+ * uint32 attnvals;
+ * int16 attlen;
+ * AttrNumber attnum;
+ * uint32 attnelems;
+ * int32 attcacheoff;
+ * bool attbyval;
+ * bool attisset;
+ * char attalign;
+ * bool attnotnull;
+ * bool atthasdef;
* } FormData_pg_attribute;
*
* ----------------------------------------------------------------
*/
-static FormData_pg_attribute sysatts[] = {
- { 0l, {"ctid"}, 27l, 0l, 6, -1, 0, -1, '\0', '\0', 'i', '\0', '\0' },
- { 0l, {"oid"}, 26l, 0l, 4, -2, 0, -1, '\001', '\0', 'i', '\0', '\0' },
- { 0l, {"xmin"}, 28l, 0l, 4, -3, 0, -1, '\0', '\0', 'i', '\0', '\0' },
- { 0l, {"cmin"}, 29l, 0l, 2, -4, 0, -1, '\001', '\0', 's', '\0', '\0' },
- { 0l, {"xmax"}, 28l, 0l, 4, -5, 0, -1, '\0', '\0', 'i', '\0', '\0' },
- { 0l, {"cmax"}, 29l, 0l, 2, -6, 0, -1, '\001', '\0', 's', '\0', '\0' },
- { 0l, {"chain"}, 27l, 0l, 6, -7, 0, -1, '\0', '\0', 'i', '\0', '\0' },
- { 0l, {"anchor"}, 27l, 0l, 6, -8, 0, -1, '\0', '\0', 'i', '\0', '\0' },
- { 0l, {"tmin"}, 702l, 0l, 4, -9, 0, -1, '\001', '\0', 'i', '\0', '\0' },
- { 0l, {"tmax"}, 702l, 0l, 4, -10, 0, -1, '\001', '\0', 'i', '\0', '\0' },
- { 0l, {"vtype"}, 18l, 0l, 1, -11, 0, -1, '\001', '\0', 'c', '\0', '\0' },
+static FormData_pg_attribute sysatts[] = {
+ {0l, {"ctid"}, 27l, 0l, 6, -1, 0, -1, '\0', '\0', 'i', '\0', '\0'},
+ {0l, {"oid"}, 26l, 0l, 4, -2, 0, -1, '\001', '\0', 'i', '\0', '\0'},
+ {0l, {"xmin"}, 28l, 0l, 4, -3, 0, -1, '\0', '\0', 'i', '\0', '\0'},
+ {0l, {"cmin"}, 29l, 0l, 2, -4, 0, -1, '\001', '\0', 's', '\0', '\0'},
+ {0l, {"xmax"}, 28l, 0l, 4, -5, 0, -1, '\0', '\0', 'i', '\0', '\0'},
+ {0l, {"cmax"}, 29l, 0l, 2, -6, 0, -1, '\001', '\0', 's', '\0', '\0'},
+ {0l, {"chain"}, 27l, 0l, 6, -7, 0, -1, '\0', '\0', 'i', '\0', '\0'},
+ {0l, {"anchor"}, 27l, 0l, 6, -8, 0, -1, '\0', '\0', 'i', '\0', '\0'},
+ {0l, {"tmin"}, 702l, 0l, 4, -9, 0, -1, '\001', '\0', 'i', '\0', '\0'},
+ {0l, {"tmax"}, 702l, 0l, 4, -10, 0, -1, '\001', '\0', 'i', '\0', '\0'},
+ {0l, {"vtype"}, 18l, 0l, 1, -11, 0, -1, '\001', '\0', 'c', '\0', '\0'},
};
/* ----------------------------------------------------------------
* RelationNameGetObjectId --
- * Returns the object identifier for a relation given its name.
+ * Returns the object identifier for a relation given its name.
*
* > The HASINDEX attribute for the relation with this name will
* > be set if it exists and if it is indicated by the call argument.
@@ -135,1574 +140,1638 @@ static FormData_pg_attribute sysatts[] = {
* probably be replaced by SearchSysCacheTuple. -cim 1/19/91
*
* Note:
- * Assumes relation name is valid.
- * Assumes relation descriptor is valid.
+ * Assumes relation name is valid.
+ * Assumes relation descriptor is valid.
* ----------------------------------------------------------------
*/
-static Oid
+static Oid
RelationNameGetObjectId(char *relationName,
- Relation pg_class,
- bool setHasIndexAttribute)
-{
- HeapScanDesc pg_class_scan;
- HeapTuple pg_class_tuple;
- Oid relationObjectId;
- Buffer buffer;
- ScanKeyData key;
-
- /*
- * If this isn't bootstrap time, we can use the system catalogs to
- * speed this up.
- */
-
- if (!IsBootstrapProcessingMode()) {
- pg_class_tuple = ClassNameIndexScan(pg_class, relationName);
- if (HeapTupleIsValid(pg_class_tuple)) {
- relationObjectId = pg_class_tuple->t_oid;
- pfree(pg_class_tuple);
- } else
- relationObjectId = InvalidOid;
-
- return (relationObjectId);
- }
-
- /* ----------------
- * Bootstrap time, do this the hard way.
- * begin a scan of pg_class for the named relation
- * ----------------
- */
- ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
- NameEqualRegProcedure,
- PointerGetDatum(relationName));
-
- pg_class_scan = heap_beginscan(pg_class, 0, NowTimeQual, 1, &key);
-
- /* ----------------
- * if we find the named relation, fetch its relation id
- * (the oid of the tuple we found).
- * ----------------
- */
- pg_class_tuple = heap_getnext(pg_class_scan, 0, &buffer);
-
- if (! HeapTupleIsValid(pg_class_tuple)) {
- relationObjectId = InvalidOid;
- } else {
- relationObjectId = pg_class_tuple->t_oid;
- ReleaseBuffer(buffer);
- }
-
- /* ----------------
- * cleanup and return results
- * ----------------
- */
- heap_endscan(pg_class_scan);
-
- return
- relationObjectId;
+ Relation pg_class,
+ bool setHasIndexAttribute)
+{
+ HeapScanDesc pg_class_scan;
+ HeapTuple pg_class_tuple;
+ Oid relationObjectId;
+ Buffer buffer;
+ ScanKeyData key;
+
+ /*
+ * If this isn't bootstrap time, we can use the system catalogs to
+ * speed this up.
+ */
+
+ if (!IsBootstrapProcessingMode())
+ {
+ pg_class_tuple = ClassNameIndexScan(pg_class, relationName);
+ if (HeapTupleIsValid(pg_class_tuple))
+ {
+ relationObjectId = pg_class_tuple->t_oid;
+ pfree(pg_class_tuple);
+ }
+ else
+ relationObjectId = InvalidOid;
+
+ return (relationObjectId);
+ }
+
+ /* ----------------
+ * Bootstrap time, do this the hard way.
+ * begin a scan of pg_class for the named relation
+ * ----------------
+ */
+ ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
+ NameEqualRegProcedure,
+ PointerGetDatum(relationName));
+
+ pg_class_scan = heap_beginscan(pg_class, 0, NowTimeQual, 1, &key);
+
+ /* ----------------
+ * if we find the named relation, fetch its relation id
+ * (the oid of the tuple we found).
+ * ----------------
+ */
+ pg_class_tuple = heap_getnext(pg_class_scan, 0, &buffer);
+
+ if (!HeapTupleIsValid(pg_class_tuple))
+ {
+ relationObjectId = InvalidOid;
+ }
+ else
+ {
+ relationObjectId = pg_class_tuple->t_oid;
+ ReleaseBuffer(buffer);
+ }
+
+ /* ----------------
+ * cleanup and return results
+ * ----------------
+ */
+ heap_endscan(pg_class_scan);
+
+ return
+ relationObjectId;
}
/* ----------------------------------------------------------------
- * GetHeapRelationOid
+ * GetHeapRelationOid
* ----------------------------------------------------------------
*/
-static Oid
+static Oid
GetHeapRelationOid(char *heapRelationName, char *indexRelationName)
{
- Relation pg_class;
- Oid indoid;
- Oid heapoid;
-
- /* ----------------
- * XXX ADD INDEXING HERE
- * ----------------
- */
- /* ----------------
- * open pg_class and get the oid of the relation
- * corresponding to the name of the index relation.
- * ----------------
- */
- pg_class = heap_openr(RelationRelationName);
-
- indoid = RelationNameGetObjectId(indexRelationName,
- pg_class,
- false);
-
- if (OidIsValid(indoid))
- elog(WARN, "Cannot create index: '%s' already exists",
- indexRelationName);
-
- /* ----------------
- * get the object id of the heap relation
- * ----------------
- */
- heapoid = RelationNameGetObjectId(heapRelationName,
- pg_class,
- true);
-
- /* ----------------
- * check that the heap relation exists..
- * ----------------
- */
- if (! OidIsValid(heapoid))
- elog(WARN, "Cannot create index on '%s': relation does not exist",
- heapRelationName);
-
- /* ----------------
- * close pg_class and return the heap relation oid
- * ----------------
- */
- heap_close(pg_class);
-
- return heapoid;
+ Relation pg_class;
+ Oid indoid;
+ Oid heapoid;
+
+ /* ----------------
+ * XXX ADD INDEXING HERE
+ * ----------------
+ */
+ /* ----------------
+ * open pg_class and get the oid of the relation
+ * corresponding to the name of the index relation.
+ * ----------------
+ */
+ pg_class = heap_openr(RelationRelationName);
+
+ indoid = RelationNameGetObjectId(indexRelationName,
+ pg_class,
+ false);
+
+ if (OidIsValid(indoid))
+ elog(WARN, "Cannot create index: '%s' already exists",
+ indexRelationName);
+
+ /* ----------------
+ * get the object id of the heap relation
+ * ----------------
+ */
+ heapoid = RelationNameGetObjectId(heapRelationName,
+ pg_class,
+ true);
+
+ /* ----------------
+ * check that the heap relation exists..
+ * ----------------
+ */
+ if (!OidIsValid(heapoid))
+ elog(WARN, "Cannot create index on '%s': relation does not exist",
+ heapRelationName);
+
+ /* ----------------
+ * close pg_class and return the heap relation oid
+ * ----------------
+ */
+ heap_close(pg_class);
+
+ return heapoid;
}
-static TupleDesc
-BuildFuncTupleDesc(FuncIndexInfo *funcInfo)
+static TupleDesc
+BuildFuncTupleDesc(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] = (AttributeTupleForm) 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);
-
- 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(WARN,"Function %s return type does not exist",FIgetname(funcInfo));
-
- /*
- * Assign some of the attributes values. Leave the rest as 0.
- */
- funcTupDesc->attrs[0]->attlen = ((TypeTupleForm)GETSTRUCT(tuple))->typlen;
- funcTupDesc->attrs[0]->atttypid = retType;
- funcTupDesc->attrs[0]->attnum = 1;
- funcTupDesc->attrs[0]->attbyval = ((TypeTupleForm)GETSTRUCT(tuple))->typbyval;
-
- /*
- * make the attributes name the same as the functions
- */
- namestrcpy(&funcTupDesc->attrs[0]->attname, funcname);
-
- return (funcTupDesc);
+ HeapTuple tuple;
+ TupleDesc funcTupDesc;
+ Oid retType;
+ char *funcname;
+ int4 nargs;
+ Oid *argtypes;
+
+ /*
+ * Allocate and zero a tuple descriptor.
+ */
+ funcTupDesc = CreateTemplateTupleDesc(1);
+ funcTupDesc->attrs[0] = (AttributeTupleForm) 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);
+
+ 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(WARN, "Function %s return type does not exist", FIgetname(funcInfo));
+
+ /*
+ * Assign some of the attributes values. Leave the rest as 0.
+ */
+ funcTupDesc->attrs[0]->attlen = ((TypeTupleForm) GETSTRUCT(tuple))->typlen;
+ funcTupDesc->attrs[0]->atttypid = retType;
+ funcTupDesc->attrs[0]->attnum = 1;
+ funcTupDesc->attrs[0]->attbyval = ((TypeTupleForm) GETSTRUCT(tuple))->typbyval;
+
+ /*
+ * make the attributes name the same as the functions
+ */
+ namestrcpy(&funcTupDesc->attrs[0]->attname, funcname);
+
+ return (funcTupDesc);
}
/* ----------------------------------------------------------------
- * ConstructTupleDescriptor
+ * ConstructTupleDescriptor
* ----------------------------------------------------------------
*/
-static TupleDesc
+static TupleDesc
ConstructTupleDescriptor(Oid heapoid,
- Relation heapRelation,
- List *attributeList,
- int numatts,
- AttrNumber attNums[])
+ Relation heapRelation,
+ List * attributeList,
+ int numatts,
+ AttrNumber attNums[])
{
- TupleDesc heapTupDesc;
- TupleDesc indexTupDesc;
- IndexElem *IndexKey;
- TypeName *IndexKeyType;
- AttrNumber atnum; /* attributeNumber[attributeOffset] */
- AttrNumber atind;
- int natts; /* RelationTupleForm->relnatts */
- char *from; /* used to simplify memcpy below */
- char *to; /* used to simplify memcpy below */
- int i;
-
- /* ----------------
- * allocate the new tuple descriptor
- * ----------------
- */
- natts = RelationGetRelationTupleForm(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) {
-
+ TupleDesc heapTupDesc;
+ TupleDesc indexTupDesc;
+ IndexElem *IndexKey;
+ TypeName *IndexKeyType;
+ AttrNumber atnum; /* attributeNumber[attributeOffset] */
+ AttrNumber atind;
+ int natts; /* RelationTupleForm->relnatts */
+ char *from; /* used to simplify memcpy below */
+ char *to; /* used to simplify memcpy below */
+ int i;
+
/* ----------------
- * get the attribute number and make sure it's valid
+ * allocate the new tuple descriptor
* ----------------
*/
- atnum = attNums[i];
- if (atnum > natts)
- elog(WARN, "Cannot create index: attribute %d does not exist",
- atnum);
- if (attributeList) {
- IndexKey = (IndexElem*) lfirst(attributeList);
- attributeList = lnext(attributeList);
- IndexKeyType = IndexKey->tname;
- } else {
- IndexKeyType = NULL;
- }
-
- indexTupDesc->attrs[i] = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
-
+ natts = RelationGetRelationTupleForm(heapRelation)->relnatts;
+
+ indexTupDesc = CreateTemplateTupleDesc(numatts);
+
/* ----------------
- * 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(WARN, "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 = RelationGetTupleDescriptor(heapRelation);
- atind = AttrNumberGetAttrOffset(atnum);
-
- from = (char *) (heapTupDesc->attrs[ atind ]);
- }
-
+
/* ----------------
- * now that we've determined the "from", let's copy
- * the tuple desc data...
+ * 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
* ----------------
*/
-
- to = (char *) (indexTupDesc->attrs[ i ]);
- memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);
-
- ((AttributeTupleForm) to)->attnum = i+1;
- ((AttributeTupleForm) to)->attcacheoff = -1;
-
- ((AttributeTupleForm) to)->attnotnull = false;
- ((AttributeTupleForm) to)->atthasdef = false;
-
- /* 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(WARN, "create index: type '%s' undefined",
- IndexKeyType->name);
- ((AttributeTupleForm) to)->atttypid = tup->t_oid;
- ((AttributeTupleForm) to)->attbyval =
- ((TypeTupleForm) ((char *)tup + tup->t_hoff))->typbyval;
- if (IndexKeyType->typlen > 0)
- ((AttributeTupleForm) to)->attlen = IndexKeyType->typlen;
- else ((AttributeTupleForm) to)->attlen =
- ((TypeTupleForm) ((char *)tup + tup->t_hoff))->typlen;
+ for (i = 0; i < numatts; i += 1)
+ {
+
+ /* ----------------
+ * get the attribute number and make sure it's valid
+ * ----------------
+ */
+ atnum = attNums[i];
+ if (atnum > natts)
+ elog(WARN, "Cannot create index: attribute %d does not exist",
+ atnum);
+ if (attributeList)
+ {
+ IndexKey = (IndexElem *) lfirst(attributeList);
+ attributeList = lnext(attributeList);
+ IndexKeyType = IndexKey->tname;
+ }
+ else
+ {
+ IndexKeyType = NULL;
+ }
+
+ indexTupDesc->attrs[i] = (AttributeTupleForm) 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(WARN, "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 = RelationGetTupleDescriptor(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);
+
+ ((AttributeTupleForm) to)->attnum = i + 1;
+ ((AttributeTupleForm) to)->attcacheoff = -1;
+
+ ((AttributeTupleForm) to)->attnotnull = false;
+ ((AttributeTupleForm) to)->atthasdef = false;
+
+ /*
+ * 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(WARN, "create index: type '%s' undefined",
+ IndexKeyType->name);
+ ((AttributeTupleForm) to)->atttypid = tup->t_oid;
+ ((AttributeTupleForm) to)->attbyval =
+ ((TypeTupleForm) ((char *) tup + tup->t_hoff))->typbyval;
+ if (IndexKeyType->typlen > 0)
+ ((AttributeTupleForm) to)->attlen = IndexKeyType->typlen;
+ else
+ ((AttributeTupleForm) to)->attlen =
+ ((TypeTupleForm) ((char *) tup + tup->t_hoff))->typlen;
+ }
+
+
+ /* ----------------
+ * now we have to drop in the proper relation descriptor
+ * into the copied tuple form's attrelid and we should be
+ * all set.
+ * ----------------
+ */
+ ((AttributeTupleForm) to)->attrelid = heapoid;
}
-
- /* ----------------
- * now we have to drop in the proper relation descriptor
- * into the copied tuple form's attrelid and we should be
- * all set.
- * ----------------
- */
- ((AttributeTupleForm) to)->attrelid = heapoid;
- }
-
- return indexTupDesc;
+ return indexTupDesc;
}
/* ----------------------------------------------------------------
* AccessMethodObjectIdGetAccessMethodTupleForm --
- * Returns the formated access method tuple given its object identifier.
+ * Returns the formated access method tuple given its object identifier.
*
* XXX ADD INDEXING
*
* Note:
- * Assumes object identifier is valid.
+ * Assumes object identifier is valid.
* ----------------------------------------------------------------
*/
Form_pg_am
AccessMethodObjectIdGetAccessMethodTupleForm(Oid accessMethodObjectId)
{
- Relation pg_am_desc;
- HeapScanDesc pg_am_scan;
- HeapTuple pg_am_tuple;
- ScanKeyData key;
- Form_pg_am form;
-
- /* ----------------
- * form a scan key for the pg_am relation
- * ----------------
- */
- ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
- ObjectIdEqualRegProcedure,
- ObjectIdGetDatum(accessMethodObjectId));
-
- /* ----------------
- * fetch the desired access method tuple
- * ----------------
- */
- pg_am_desc = heap_openr(AccessMethodRelationName);
- pg_am_scan = heap_beginscan(pg_am_desc, 0, NowTimeQual, 1, &key);
-
- pg_am_tuple = heap_getnext(pg_am_scan, 0, (Buffer *)NULL);
-
- /* ----------------
- * return NULL if not found
- * ----------------
- */
- if (! HeapTupleIsValid(pg_am_tuple)) {
+ Relation pg_am_desc;
+ HeapScanDesc pg_am_scan;
+ HeapTuple pg_am_tuple;
+ ScanKeyData key;
+ Form_pg_am form;
+
+ /* ----------------
+ * form a scan key for the pg_am relation
+ * ----------------
+ */
+ ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
+ ObjectIdEqualRegProcedure,
+ ObjectIdGetDatum(accessMethodObjectId));
+
+ /* ----------------
+ * fetch the desired access method tuple
+ * ----------------
+ */
+ pg_am_desc = heap_openr(AccessMethodRelationName);
+ pg_am_scan = heap_beginscan(pg_am_desc, 0, NowTimeQual, 1, &key);
+
+ pg_am_tuple = heap_getnext(pg_am_scan, 0, (Buffer *) NULL);
+
+ /* ----------------
+ * 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
+ * ----------------
+ */
+ form = (Form_pg_am) palloc(sizeof *form);
+ memcpy(form, GETSTRUCT(pg_am_tuple), sizeof *form);
+
heap_endscan(pg_am_scan);
heap_close(pg_am_desc);
- return (NULL);
- }
-
- /* ----------------
- * if found am tuple, then copy the form and return the copy
- * ----------------
- */
- form = (Form_pg_am)palloc(sizeof *form);
- memcpy(form, GETSTRUCT(pg_am_tuple), sizeof *form);
-
- heap_endscan(pg_am_scan);
- heap_close(pg_am_desc);
-
- return (form);
+
+ return (form);
}
/* ----------------------------------------------------------------
- * ConstructIndexReldesc
+ * ConstructIndexReldesc
* ----------------------------------------------------------------
*/
static void
ConstructIndexReldesc(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 =
- AccessMethodObjectIdGetAccessMethodTupleForm(amoid);
-
- MemoryContextSwitchTo(oldcxt);
-
- /* ----------------
- * XXX missing the initialization of some other fields
- * ----------------
- */
-
- indexRelation->rd_rel->relowner = GetUserId();
-
- indexRelation->rd_rel->relam = amoid;
- indexRelation->rd_rel->reltuples = 1; /* XXX */
- indexRelation->rd_rel->relexpires = 0; /* XXX */
- indexRelation->rd_rel->relpreserved = 0; /* XXX */
- indexRelation->rd_rel->relkind = RELKIND_INDEX;
- indexRelation->rd_rel->relarch = 'n'; /* XXX */
+ 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 =
+ AccessMethodObjectIdGetAccessMethodTupleForm(amoid);
+
+ MemoryContextSwitchTo(oldcxt);
+
+ /* ----------------
+ * XXX missing the initialization of some other fields
+ * ----------------
+ */
+
+ indexRelation->rd_rel->relowner = GetUserId();
+
+ indexRelation->rd_rel->relam = amoid;
+ indexRelation->rd_rel->reltuples = 1; /* XXX */
+ indexRelation->rd_rel->relexpires = 0; /* XXX */
+ indexRelation->rd_rel->relpreserved = 0; /* XXX */
+ indexRelation->rd_rel->relkind = RELKIND_INDEX;
+ indexRelation->rd_rel->relarch = 'n'; /* XXX */
}
/* ----------------------------------------------------------------
- * UpdateRelationRelation
+ * UpdateRelationRelation
* ----------------------------------------------------------------
*/
-static Oid
+static Oid
UpdateRelationRelation(Relation indexRelation)
{
- Relation pg_class;
- HeapTuple tuple;
- Oid tupleOid;
- Relation idescs[Num_pg_class_indices];
-
- pg_class = heap_openr(RelationRelationName);
-
- /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
- tuple = heap_addheader(Natts_pg_class_fixed,
- sizeof(*indexRelation->rd_rel),
- (char *) indexRelation->rd_rel);
-
- /* ----------------
- * the new tuple must have the same oid as the relcache entry for the
- * index. sure would be embarassing to do this sort of thing in polite
- * company.
- * ----------------
- */
- tuple->t_oid = indexRelation->rd_id;
- heap_insert(pg_class, tuple);
-
- /*
- * During normal processing, we need to make sure that the system
- * catalog indices are correct. Bootstrap (initdb) time doesn't
- * require this, because we make sure that the indices are correct
- * just before exiting.
- */
-
- if (!IsBootstrapProcessingMode()) {
- CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
- CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
- CatalogCloseIndices(Num_pg_class_indices, idescs);
- }
-
- tupleOid = tuple->t_oid;
- pfree(tuple);
- heap_close(pg_class);
-
- return(tupleOid);
+ Relation pg_class;
+ HeapTuple tuple;
+ Oid tupleOid;
+ Relation idescs[Num_pg_class_indices];
+
+ pg_class = heap_openr(RelationRelationName);
+
+ /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
+ tuple = heap_addheader(Natts_pg_class_fixed,
+ sizeof(*indexRelation->rd_rel),
+ (char *) indexRelation->rd_rel);
+
+ /* ----------------
+ * the new tuple must have the same oid as the relcache entry for the
+ * index. sure would be embarassing to do this sort of thing in polite
+ * company.
+ * ----------------
+ */
+ tuple->t_oid = indexRelation->rd_id;
+ heap_insert(pg_class, tuple);
+
+ /*
+ * During normal processing, we need to make sure that the system
+ * catalog indices are correct. Bootstrap (initdb) time doesn't
+ * require this, because we make sure that the indices are correct
+ * just before exiting.
+ */
+
+ if (!IsBootstrapProcessingMode())
+ {
+ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
+ CatalogCloseIndices(Num_pg_class_indices, idescs);
+ }
+
+ tupleOid = tuple->t_oid;
+ pfree(tuple);
+ heap_close(pg_class);
+
+ return (tupleOid);
}
/* ----------------------------------------------------------------
- * InitializeAttributeOids
+ * InitializeAttributeOids
* ----------------------------------------------------------------
*/
static void
InitializeAttributeOids(Relation indexRelation,
- int numatts,
- Oid indexoid)
+ int numatts,
+ Oid indexoid)
{
- TupleDesc tupleDescriptor;
- int i;
-
- tupleDescriptor = RelationGetTupleDescriptor(indexRelation);
-
- for (i = 0; i < numatts; i += 1)
- tupleDescriptor->attrs[i]->attrelid = indexoid;
+ TupleDesc tupleDescriptor;
+ int i;
+
+ tupleDescriptor = RelationGetTupleDescriptor(indexRelation);
+
+ for (i = 0; i < numatts; i += 1)
+ tupleDescriptor->attrs[i]->attrelid = indexoid;
}
/* ----------------------------------------------------------------
- * AppendAttributeTuples
+ * AppendAttributeTuples
*
- * XXX For now, only change the ATTNUM attribute value
+ * XXX For now, only change the ATTNUM attribute value
* ----------------------------------------------------------------
*/
static void
AppendAttributeTuples(Relation indexRelation, int numatts)
{
- Relation pg_attribute;
- HeapTuple tuple;
- HeapTuple newtuple;
- bool hasind;
- Relation idescs[Num_pg_attr_indices];
-
- Datum value[ Natts_pg_attribute ];
- char nullv[ Natts_pg_attribute ];
- char replace[ Natts_pg_attribute ];
-
- TupleDesc indexTupDesc;
- int i;
-
- /* ----------------
- * open the attribute relation
- * XXX ADD INDEXING
- * ----------------
- */
- pg_attribute = heap_openr(AttributeRelationName);
-
- /* ----------------
- * initialize null[], replace[] and value[]
- * ----------------
- */
- memset(nullv, ' ', Natts_pg_attribute);
- memset(replace, ' ', Natts_pg_attribute);
-
- /* ----------------
- * create the first attribute tuple.
- * XXX For now, only change the ATTNUM attribute value
- * ----------------
- */
- replace[ Anum_pg_attribute_attnum - 1 ] = 'r';
- replace[ Anum_pg_attribute_attcacheoff - 1 ] = 'r';
-
- value[ Anum_pg_attribute_attnum - 1 ] = Int16GetDatum(1);
- value[ Anum_pg_attribute_attcacheoff - 1 ] = Int32GetDatum(-1);
-
- tuple = heap_addheader(Natts_pg_attribute,
- sizeof *(indexRelation->rd_att->attrs[0]),
- (char *)(indexRelation->rd_att->attrs[0]));
-
- hasind = false;
- if (!IsBootstrapProcessingMode() && pg_attribute->rd_rel->relhasindex) {
- hasind = true;
- CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
- }
-
- /* ----------------
- * insert the first attribute tuple.
- * ----------------
- */
- tuple = heap_modifytuple(tuple,
- InvalidBuffer,
- pg_attribute,
- value,
- nullv,
- replace);
-
- heap_insert(pg_attribute, tuple);
- if (hasind)
- CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, tuple);
-
- /* ----------------
- * now we use the information in the index tuple
- * descriptor to form the remaining attribute tuples.
- * ----------------
- */
- indexTupDesc = RelationGetTupleDescriptor(indexRelation);
-
- for (i = 1; i < numatts; i += 1) {
+ Relation pg_attribute;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ bool hasind;
+ Relation idescs[Num_pg_attr_indices];
+
+ Datum value[Natts_pg_attribute];
+ char nullv[Natts_pg_attribute];
+ char replace[Natts_pg_attribute];
+
+ TupleDesc indexTupDesc;
+ int i;
+
/* ----------------
- * process the remaining attributes...
+ * open the attribute relation
+ * XXX ADD INDEXING
* ----------------
*/
- memmove(GETSTRUCT(tuple),
- (char *)indexTupDesc->attrs[i],
- sizeof (FormData_pg_attribute));
-
- value[ Anum_pg_attribute_attnum - 1 ] = Int16GetDatum(i + 1);
-
- newtuple = heap_modifytuple(tuple,
- InvalidBuffer,
- pg_attribute,
- value,
- nullv,
- replace);
-
- heap_insert(pg_attribute, newtuple);
+ pg_attribute = heap_openr(AttributeRelationName);
+
+ /* ----------------
+ * initialize null[], replace[] and value[]
+ * ----------------
+ */
+ memset(nullv, ' ', Natts_pg_attribute);
+ memset(replace, ' ', Natts_pg_attribute);
+
+ /* ----------------
+ * create the first attribute tuple.
+ * XXX For now, only change the ATTNUM attribute value
+ * ----------------
+ */
+ replace[Anum_pg_attribute_attnum - 1] = 'r';
+ replace[Anum_pg_attribute_attcacheoff - 1] = 'r';
+
+ value[Anum_pg_attribute_attnum - 1] = Int16GetDatum(1);
+ value[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
+
+ tuple = heap_addheader(Natts_pg_attribute,
+ sizeof *(indexRelation->rd_att->attrs[0]),
+ (char *) (indexRelation->rd_att->attrs[0]));
+
+ hasind = false;
+ if (!IsBootstrapProcessingMode() && pg_attribute->rd_rel->relhasindex)
+ {
+ hasind = true;
+ CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
+ }
+
+ /* ----------------
+ * insert the first attribute tuple.
+ * ----------------
+ */
+ tuple = heap_modifytuple(tuple,
+ InvalidBuffer,
+ pg_attribute,
+ value,
+ nullv,
+ replace);
+
+ heap_insert(pg_attribute, tuple);
if (hasind)
- CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, newtuple);
-
+ CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, tuple);
+
+ /* ----------------
+ * now we use the information in the index tuple
+ * descriptor to form the remaining attribute tuples.
+ * ----------------
+ */
+ indexTupDesc = RelationGetTupleDescriptor(indexRelation);
+
+ for (i = 1; i < numatts; i += 1)
+ {
+ /* ----------------
+ * process the remaining attributes...
+ * ----------------
+ */
+ memmove(GETSTRUCT(tuple),
+ (char *) indexTupDesc->attrs[i],
+ sizeof(FormData_pg_attribute));
+
+ value[Anum_pg_attribute_attnum - 1] = Int16GetDatum(i + 1);
+
+ newtuple = heap_modifytuple(tuple,
+ InvalidBuffer,
+ pg_attribute,
+ value,
+ nullv,
+ replace);
+
+ heap_insert(pg_attribute, newtuple);
+ if (hasind)
+ CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, newtuple);
+
+ /* ----------------
+ * ModifyHeapTuple returns a new copy of a tuple
+ * so we free the original and use the copy..
+ * ----------------
+ */
+ pfree(tuple);
+ tuple = newtuple;
+ }
+
/* ----------------
- * ModifyHeapTuple returns a new copy of a tuple
- * so we free the original and use the copy..
+ * close the attribute relation and free the tuple
* ----------------
*/
+ heap_close(pg_attribute);
+
+ if (hasind)
+ CatalogCloseIndices(Num_pg_attr_indices, idescs);
+
pfree(tuple);
- tuple = newtuple;
- }
-
- /* ----------------
- * close the attribute relation and free the tuple
- * ----------------
- */
- heap_close(pg_attribute);
-
- if (hasind)
- CatalogCloseIndices(Num_pg_attr_indices, idescs);
-
- pfree(tuple);
}
/* ----------------------------------------------------------------
- * UpdateIndexRelation
+ * UpdateIndexRelation
* ----------------------------------------------------------------
*/
static void
UpdateIndexRelation(Oid indexoid,
- Oid heapoid,
- FuncIndexInfo *funcInfo,
- int natts,
- AttrNumber attNums[],
- Oid classOids[],
- Node *predicate,
- List *attributeList,
- bool islossy,
- bool unique)
+ Oid heapoid,
+ FuncIndexInfo * funcInfo,
+ int natts,
+ AttrNumber attNums[],
+ Oid classOids[],
+ Node * predicate,
+ List * attributeList,
+ bool islossy,
+ bool unique)
{
- IndexTupleForm indexForm;
- IndexElem *IndexKey;
- char *predString;
- text *predText;
- int predLen, itupLen;
- Relation pg_index;
- HeapTuple tuple;
- int i;
-
- /* ----------------
- * allocate an IndexTupleForm big enough to hold the
- * index-predicate (if any) in string form
- * ----------------
- */
- if (predicate != NULL) {
- predString = nodeToString(predicate);
- predText = (text *)fmgr(F_TEXTIN, predString);
- pfree(predString);
- } else {
- predText = (text *)fmgr(F_TEXTIN, "");
- }
- predLen = VARSIZE(predText);
- itupLen = predLen + sizeof(FormData_pg_index);
- indexForm = (IndexTupleForm) palloc(itupLen);
-
- memmove((char *)& indexForm->indpred, (char *)predText, predLen);
-
- /* ----------------
- * store the oid information into the index tuple form
- * ----------------
- */
- indexForm->indrelid = heapoid;
- indexForm->indexrelid = indexoid;
- indexForm->indproc = (PointerIsValid(funcInfo)) ?
- FIgetProcOid(funcInfo) : InvalidOid;
- indexForm->indislossy = islossy;
- indexForm->indisunique = unique;
-
- indexForm->indhaskeytype = 0;
- while (attributeList != NIL )
- {
- IndexKey = (IndexElem*) lfirst(attributeList);
- if ( IndexKey->tname != NULL )
+ IndexTupleForm indexForm;
+ IndexElem *IndexKey;
+ char *predString;
+ text *predText;
+ int predLen,
+ itupLen;
+ Relation pg_index;
+ HeapTuple tuple;
+ int i;
+
+ /* ----------------
+ * allocate an IndexTupleForm big enough to hold the
+ * index-predicate (if any) in string form
+ * ----------------
+ */
+ if (predicate != NULL)
{
- indexForm->indhaskeytype = 1;
- break;
- }
- attributeList = lnext(attributeList);
- }
-
- memset((char *)& indexForm->indkey[0], 0, sizeof indexForm->indkey);
- memset((char *)& indexForm->indclass[0], 0, sizeof indexForm->indclass);
-
- /* ----------------
- * copy index key and op class information
- * ----------------
- */
- for (i = 0; i < natts; i += 1) {
- indexForm->indkey[i] = attNums[i];
- indexForm->indclass[i] = classOids[i];
- }
- /*
- * If we have a functional index, add all attribute arguments
- */
- if (PointerIsValid(funcInfo))
+ predString = nodeToString(predicate);
+ predText = (text *) fmgr(F_TEXTIN, predString);
+ pfree(predString);
+ }
+ else
{
- for (i=1; i < FIgetnArgs(funcInfo); i++)
- indexForm->indkey[i] = attNums[i];
+ predText = (text *) fmgr(F_TEXTIN, "");
}
-
- indexForm->indisclustered = '\0'; /* XXX constant */
- indexForm->indisarchived = '\0'; /* XXX constant */
-
- /* ----------------
- * open the system catalog index relation
- * ----------------
- */
- pg_index = heap_openr(IndexRelationName);
-
- /* ----------------
- * form a tuple to insert into pg_index
- * ----------------
- */
- tuple = heap_addheader(Natts_pg_index,
- itupLen,
- (char *)indexForm);
-
- /* ----------------
- * insert the tuple into the pg_index
- * XXX ADD INDEX TUPLES TOO
- * ----------------
- */
- heap_insert(pg_index, tuple);
-
- /* ----------------
- * close the relation and free the tuple
- * ----------------
- */
- heap_close(pg_index);
- pfree(predText);
- pfree(indexForm);
- pfree(tuple);
+ predLen = VARSIZE(predText);
+ itupLen = predLen + sizeof(FormData_pg_index);
+ indexForm = (IndexTupleForm) palloc(itupLen);
+
+ memmove((char *) &indexForm->indpred, (char *) predText, predLen);
+
+ /* ----------------
+ * store the oid information into the index tuple form
+ * ----------------
+ */
+ indexForm->indrelid = heapoid;
+ indexForm->indexrelid = indexoid;
+ indexForm->indproc = (PointerIsValid(funcInfo)) ?
+ FIgetProcOid(funcInfo) : InvalidOid;
+ indexForm->indislossy = islossy;
+ indexForm->indisunique = unique;
+
+ indexForm->indhaskeytype = 0;
+ while (attributeList != NIL)
+ {
+ IndexKey = (IndexElem *) lfirst(attributeList);
+ if (IndexKey->tname != NULL)
+ {
+ indexForm->indhaskeytype = 1;
+ break;
+ }
+ attributeList = lnext(attributeList);
+ }
+
+ memset((char *) &indexForm->indkey[0], 0, sizeof indexForm->indkey);
+ memset((char *) &indexForm->indclass[0], 0, sizeof indexForm->indclass);
+
+ /* ----------------
+ * copy index key and op class information
+ * ----------------
+ */
+ for (i = 0; i < natts; i += 1)
+ {
+ indexForm->indkey[i] = attNums[i];
+ indexForm->indclass[i] = classOids[i];
+ }
+
+ /*
+ * If we have a functional index, add all attribute arguments
+ */
+ if (PointerIsValid(funcInfo))
+ {
+ for (i = 1; i < FIgetnArgs(funcInfo); i++)
+ indexForm->indkey[i] = attNums[i];
+ }
+
+ indexForm->indisclustered = '\0'; /* XXX constant */
+ indexForm->indisarchived = '\0'; /* XXX constant */
+
+ /* ----------------
+ * open the system catalog index relation
+ * ----------------
+ */
+ pg_index = heap_openr(IndexRelationName);
+
+ /* ----------------
+ * form a tuple to insert into pg_index
+ * ----------------
+ */
+ tuple = heap_addheader(Natts_pg_index,
+ itupLen,
+ (char *) indexForm);
+
+ /* ----------------
+ * insert the tuple into the pg_index
+ * XXX ADD INDEX TUPLES TOO
+ * ----------------
+ */
+ heap_insert(pg_index, tuple);
+
+ /* ----------------
+ * close the relation and free the tuple
+ * ----------------
+ */
+ heap_close(pg_index);
+ pfree(predText);
+ pfree(indexForm);
+ pfree(tuple);
}
/* ----------------------------------------------------------------
- * UpdateIndexPredicate
+ * UpdateIndexPredicate
* ----------------------------------------------------------------
*/
void
-UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
+UpdateIndexPredicate(Oid indexoid, Node * oldPred, Node * predicate)
{
- Node *newPred;
- char *predString;
- text *predText;
- Relation pg_index;
- HeapTuple tuple;
- HeapTuple newtup;
- ScanKeyData entry;
- HeapScanDesc scan;
- Buffer buffer;
- int i;
- Datum values[Natts_pg_index];
- char nulls[Natts_pg_index];
- char replace[Natts_pg_index];
-
- /*
- * Construct newPred as a CNF expression equivalent to the OR of the
- * original partial-index predicate ("oldPred") and the extension
- * predicate ("predicate").
- *
- * This should really try to process the result to change things like
- * "a>2 OR a>1" to simply "a>1", but for now all it does is make sure
- * that if the extension predicate is NULL (i.e., it is being extended
- * to be a complete index), then newPred will be NULL - in effect,
- * changing "a>2 OR TRUE" to "TRUE". --Nels, Jan '93
- */
- newPred = NULL;
- if (predicate != NULL) {
- newPred =
- (Node*)make_orclause(lcons(make_andclause((List*)predicate),
- lcons(make_andclause((List*)oldPred),
- NIL)));
- newPred = (Node*)cnfify((Expr*)newPred, true);
- }
-
- /* translate the index-predicate to string form */
- if (newPred != NULL) {
- predString = nodeToString(newPred);
- predText = (text *)fmgr(F_TEXTIN, predString);
- pfree(predString);
- } else {
- predText = (text *)fmgr(F_TEXTIN, "");
- }
-
- /* open the index system catalog relation */
- pg_index = heap_openr(IndexRelationName);
-
- ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indexrelid,
- ObjectIdEqualRegProcedure,
- ObjectIdGetDatum(indexoid));
-
- scan = heap_beginscan(pg_index, 0, NowTimeQual, 1, &entry);
- tuple = heap_getnext(scan, 0, &buffer);
- heap_endscan(scan);
-
- for (i = 0; i < Natts_pg_index; i++) {
- nulls[i] = heap_attisnull(tuple, i+1) ? 'n' : ' ';
- replace[i] = ' ';
- values[i] = (Datum) NULL;
- }
-
- replace[Anum_pg_index_indpred - 1] = 'r';
- values[Anum_pg_index_indpred - 1] = (Datum) predText;
-
- newtup = heap_modifytuple(tuple, buffer, pg_index, values, nulls, replace);
-
- heap_replace(pg_index, &(newtup->t_ctid), newtup);
-
- heap_close(pg_index);
- pfree(predText);
+ Node *newPred;
+ char *predString;
+ text *predText;
+ Relation pg_index;
+ HeapTuple tuple;
+ HeapTuple newtup;
+ ScanKeyData entry;
+ HeapScanDesc scan;
+ Buffer buffer;
+ int i;
+ Datum values[Natts_pg_index];
+ char nulls[Natts_pg_index];
+ char replace[Natts_pg_index];
+
+ /*
+ * Construct newPred as a CNF expression equivalent to the OR of the
+ * original partial-index predicate ("oldPred") and the extension
+ * predicate ("predicate").
+ *
+ * This should really try to process the result to change things like
+ * "a>2 OR a>1" to simply "a>1", but for now all it does is make sure
+ * that if the extension predicate is NULL (i.e., it is being extended
+ * to be a complete index), then newPred will be NULL - in effect,
+ * changing "a>2 OR TRUE" to "TRUE". --Nels, Jan '93
+ */
+ newPred = NULL;
+ if (predicate != NULL)
+ {
+ newPred =
+ (Node *) make_orclause(lcons(make_andclause((List *) predicate),
+ lcons(make_andclause((List *) oldPred),
+ NIL)));
+ newPred = (Node *) cnfify((Expr *) newPred, true);
+ }
+
+ /* translate the index-predicate to string form */
+ if (newPred != NULL)
+ {
+ predString = nodeToString(newPred);
+ predText = (text *) fmgr(F_TEXTIN, predString);
+ pfree(predString);
+ }
+ else
+ {
+ predText = (text *) fmgr(F_TEXTIN, "");
+ }
+
+ /* open the index system catalog relation */
+ pg_index = heap_openr(IndexRelationName);
+
+ ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indexrelid,
+ ObjectIdEqualRegProcedure,
+ ObjectIdGetDatum(indexoid));
+
+ scan = heap_beginscan(pg_index, 0, NowTimeQual, 1, &entry);
+ tuple = heap_getnext(scan, 0, &buffer);
+ heap_endscan(scan);
+
+ for (i = 0; i < Natts_pg_index; i++)
+ {
+ nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';
+ replace[i] = ' ';
+ values[i] = (Datum) NULL;
+ }
+
+ replace[Anum_pg_index_indpred - 1] = 'r';
+ values[Anum_pg_index_indpred - 1] = (Datum) predText;
+
+ newtup = heap_modifytuple(tuple, buffer, pg_index, values, nulls, replace);
+
+ heap_replace(pg_index, &(newtup->t_ctid), newtup);
+
+ heap_close(pg_index);
+ pfree(predText);
}
/* ----------------------------------------------------------------
- * InitIndexStrategy
+ * InitIndexStrategy
* ----------------------------------------------------------------
*/
void
InitIndexStrategy(int numatts,
- Relation indexRelation,
- Oid accessMethodObjectId)
+ Relation indexRelation,
+ Oid accessMethodObjectId)
{
- IndexStrategy strategy;
- RegProcedure *support;
- uint16 amstrategies;
- uint16 amsupport;
- Oid attrelid;
- Size strsize;
- extern GlobalMemory CacheCxt;
-
- /* ----------------
- * get information from the index relation descriptor
- * ----------------
- */
- attrelid = indexRelation->rd_att->attrs[0]->attrelid;
- amstrategies = indexRelation->rd_am->amstrategies;
- amsupport = indexRelation->rd_am->amsupport;
-
- /* ----------------
- * get the size of the strategy
- * ----------------
- */
- strsize = AttributeNumberGetIndexStrategySize(numatts, amstrategies);
-
- /* ----------------
- * allocate the new index strategy structure
- *
- * the index strategy has to be allocated in the same
- * context as the relation descriptor cache or else
- * it will be lost at the end of the transaction.
- * ----------------
- */
- if (!CacheCxt)
- CacheCxt = CreateGlobalMemory("Cache");
-
- strategy = (IndexStrategy)
- MemoryContextAlloc((MemoryContext)CacheCxt, strsize);
-
- if (amsupport > 0) {
- strsize = numatts * (amsupport * sizeof(RegProcedure));
- support = (RegProcedure *) MemoryContextAlloc((MemoryContext)CacheCxt,
- strsize);
- } else {
- support = (RegProcedure *) NULL;
- }
-
- /* ----------------
- * fill in the index strategy structure with information
- * from the catalogs. Note: we use heap override mode
- * in order to be allowed to see the correct information in the
- * catalogs, even though our transaction has not yet committed.
- * ----------------
- */
- setheapoverride(1);
-
- IndexSupportInitialize(strategy, support,
- attrelid, accessMethodObjectId,
- amstrategies, amsupport, numatts);
-
- setheapoverride(0);
-
- /* ----------------
- * store the strategy information in the index reldesc
- * ----------------
- */
- RelationSetIndexSupport(indexRelation, strategy, support);
+ IndexStrategy strategy;
+ RegProcedure *support;
+ uint16 amstrategies;
+ uint16 amsupport;
+ Oid attrelid;
+ Size strsize;
+ extern GlobalMemory CacheCxt;
+
+ /* ----------------
+ * get information from the index relation descriptor
+ * ----------------
+ */
+ attrelid = indexRelation->rd_att->attrs[0]->attrelid;
+ amstrategies = indexRelation->rd_am->amstrategies;
+ amsupport = indexRelation->rd_am->amsupport;
+
+ /* ----------------
+ * get the size of the strategy
+ * ----------------
+ */
+ strsize = AttributeNumberGetIndexStrategySize(numatts, amstrategies);
+
+ /* ----------------
+ * allocate the new index strategy structure
+ *
+ * the index strategy has to be allocated in the same
+ * context as the relation descriptor cache or else
+ * it will be lost at the end of the transaction.
+ * ----------------
+ */
+ if (!CacheCxt)
+ CacheCxt = CreateGlobalMemory("Cache");
+
+ strategy = (IndexStrategy)
+ MemoryContextAlloc((MemoryContext) CacheCxt, strsize);
+
+ if (amsupport > 0)
+ {
+ strsize = numatts * (amsupport * sizeof(RegProcedure));
+ support = (RegProcedure *) MemoryContextAlloc((MemoryContext) CacheCxt,
+ strsize);
+ }
+ else
+ {
+ support = (RegProcedure *) NULL;
+ }
+
+ /* ----------------
+ * fill in the index strategy structure with information
+ * from the catalogs. Note: we use heap override mode
+ * in order to be allowed to see the correct information in the
+ * catalogs, even though our transaction has not yet committed.
+ * ----------------
+ */
+ setheapoverride(1);
+
+ IndexSupportInitialize(strategy, support,
+ attrelid, accessMethodObjectId,
+ amstrategies, amsupport, numatts);
+
+ setheapoverride(0);
+
+ /* ----------------
+ * store the strategy information in the index reldesc
+ * ----------------
+ */
+ RelationSetIndexSupport(indexRelation, strategy, support);
}
/* ----------------------------------------------------------------
- * index_create
+ * index_create
* ----------------------------------------------------------------
*/
void
index_create(char *heapRelationName,
- char *indexRelationName,
- FuncIndexInfo *funcInfo,
- List *attributeList,
- Oid accessMethodObjectId,
- int numatts,
- AttrNumber attNums[],
- Oid classObjectId[],
- uint16 parameterCount,
- Datum *parameter,
- Node *predicate,
- bool islossy,
- bool unique)
+ char *indexRelationName,
+ FuncIndexInfo * funcInfo,
+ List * attributeList,
+ Oid accessMethodObjectId,
+ int numatts,
+ AttrNumber attNums[],
+ Oid classObjectId[],
+ uint16 parameterCount,
+ Datum * parameter,
+ Node * predicate,
+ bool islossy,
+ bool unique)
{
- Relation heapRelation;
- Relation indexRelation;
- TupleDesc indexTupDesc;
- Oid heapoid;
- Oid indexoid;
- PredInfo *predInfo;
-
- /* ----------------
- * check parameters
- * ----------------
- */
- if (numatts < 1)
- elog(WARN, "must index at least one attribute");
-
- /* ----------------
- * get heap relation oid and open the heap relation
- * XXX ADD INDEXING
- * ----------------
- */
- heapoid = GetHeapRelationOid(heapRelationName, indexRelationName);
-
- heapRelation = heap_open(heapoid);
-
- /* ----------------
- * write lock heap to guarantee exclusive access
- * ----------------
- */
-
- RelationSetLockForWrite(heapRelation);
-
- /* ----------------
- * construct new tuple descriptor
- * ----------------
- */
- if (PointerIsValid(funcInfo))
- indexTupDesc = BuildFuncTupleDesc(funcInfo);
- else
- indexTupDesc = ConstructTupleDescriptor(heapoid,
- heapRelation,
- attributeList,
- numatts,
- attNums);
-
- /* ----------------
- * create the index relation
- * ----------------
- */
- indexRelation = heap_creatr(indexRelationName,
- DEFAULT_SMGR,
- indexTupDesc);
-
- /* ----------------
- * construct the index relation descriptor
- *
- * XXX should have a proper way to create cataloged relations
- * ----------------
- */
- ConstructIndexReldesc(indexRelation, accessMethodObjectId);
-
- /* ----------------
- * add index to catalogs
- * (append RELATION tuple)
- * ----------------
- */
- indexoid = UpdateRelationRelation(indexRelation);
-
- /* ----------------
- * Now get the index procedure (only relevant for functional indices).
- * ----------------
- */
-
- if (PointerIsValid(funcInfo))
+ Relation heapRelation;
+ Relation indexRelation;
+ TupleDesc indexTupDesc;
+ Oid heapoid;
+ Oid indexoid;
+ PredInfo *predInfo;
+
+ /* ----------------
+ * check parameters
+ * ----------------
+ */
+ if (numatts < 1)
+ elog(WARN, "must index at least one attribute");
+
+ /* ----------------
+ * get heap relation oid and open the heap relation
+ * XXX ADD INDEXING
+ * ----------------
+ */
+ heapoid = GetHeapRelationOid(heapRelationName, indexRelationName);
+
+ heapRelation = heap_open(heapoid);
+
+ /* ----------------
+ * write lock heap to guarantee exclusive access
+ * ----------------
+ */
+
+ RelationSetLockForWrite(heapRelation);
+
+ /* ----------------
+ * construct new tuple descriptor
+ * ----------------
+ */
+ if (PointerIsValid(funcInfo))
+ indexTupDesc = BuildFuncTupleDesc(funcInfo);
+ else
+ indexTupDesc = ConstructTupleDescriptor(heapoid,
+ heapRelation,
+ attributeList,
+ numatts,
+ attNums);
+
+ /* ----------------
+ * create the index relation
+ * ----------------
+ */
+ indexRelation = heap_creatr(indexRelationName,
+ DEFAULT_SMGR,
+ indexTupDesc);
+
+ /* ----------------
+ * construct the index relation descriptor
+ *
+ * XXX should have a proper way to create cataloged relations
+ * ----------------
+ */
+ ConstructIndexReldesc(indexRelation, accessMethodObjectId);
+
+ /* ----------------
+ * add index to catalogs
+ * (append RELATION tuple)
+ * ----------------
+ */
+ indexoid = UpdateRelationRelation(indexRelation);
+
+ /* ----------------
+ * Now get the index procedure (only relevant for functional indices).
+ * ----------------
+ */
+
+ if (PointerIsValid(funcInfo))
{
- HeapTuple proc_tup;
-
- proc_tup = SearchSysCacheTuple(PRONAME,
- PointerGetDatum(FIgetname(funcInfo)),
- Int32GetDatum(FIgetnArgs(funcInfo)),
- PointerGetDatum(FIgetArglist(funcInfo)),
- 0);
-
- if (!HeapTupleIsValid(proc_tup)) {
- func_error("index_create", FIgetname(funcInfo),
- FIgetnArgs(funcInfo),
- FIgetArglist(funcInfo));
- }
- FIgetProcOid(funcInfo) = proc_tup->t_oid;
+ HeapTuple proc_tup;
+
+ proc_tup = SearchSysCacheTuple(PRONAME,
+ PointerGetDatum(FIgetname(funcInfo)),
+ Int32GetDatum(FIgetnArgs(funcInfo)),
+ PointerGetDatum(FIgetArglist(funcInfo)),
+ 0);
+
+ if (!HeapTupleIsValid(proc_tup))
+ {
+ func_error("index_create", FIgetname(funcInfo),
+ FIgetnArgs(funcInfo),
+ FIgetArglist(funcInfo));
+ }
+ FIgetProcOid(funcInfo) = proc_tup->t_oid;
+ }
+
+ /* ----------------
+ * now update the object id's of all the attribute
+ * tuple forms in the index relation's tuple descriptor
+ * ----------------
+ */
+ InitializeAttributeOids(indexRelation, numatts, indexoid);
+
+ /* ----------------
+ * append ATTRIBUTE tuples
+ * ----------------
+ */
+ AppendAttributeTuples(indexRelation, numatts);
+
+ /* ----------------
+ * update pg_index
+ * (append INDEX tuple)
+ *
+ * Note that this stows away a representation of "predicate".
+ * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
+ * ----------------
+ */
+ UpdateIndexRelation(indexoid, heapoid, funcInfo,
+ numatts, attNums, classObjectId, predicate,
+ attributeList, islossy, unique);
+
+ predInfo = (PredInfo *) palloc(sizeof(PredInfo));
+ predInfo->pred = predicate;
+ predInfo->oldPred = NULL;
+
+ /* ----------------
+ * initialize the index strategy
+ * ----------------
+ */
+ InitIndexStrategy(numatts, indexRelation, accessMethodObjectId);
+
+ /*
+ * If this is bootstrap (initdb) time, then we don't actually fill in
+ * the index yet. We'll be creating more indices and classes later,
+ * so we delay filling them in until just before we're done with
+ * bootstrapping. Otherwise, we call the routine that constructs the
+ * index. The heap and index relations are closed by index_build().
+ */
+ if (IsBootstrapProcessingMode())
+ {
+ index_register(heapRelationName, indexRelationName, numatts, attNums,
+ parameterCount, parameter, funcInfo, predInfo);
+ }
+ else
+ {
+ heapRelation = heap_openr(heapRelationName);
+ index_build(heapRelation, indexRelation, numatts, attNums,
+ parameterCount, parameter, funcInfo, predInfo);
}
-
- /* ----------------
- * now update the object id's of all the attribute
- * tuple forms in the index relation's tuple descriptor
- * ----------------
- */
- InitializeAttributeOids(indexRelation, numatts, indexoid);
-
- /* ----------------
- * append ATTRIBUTE tuples
- * ----------------
- */
- AppendAttributeTuples(indexRelation, numatts);
-
- /* ----------------
- * update pg_index
- * (append INDEX tuple)
- *
- * Note that this stows away a representation of "predicate".
- * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
- * ----------------
- */
- UpdateIndexRelation(indexoid, heapoid, funcInfo,
- numatts, attNums, classObjectId, predicate,
- attributeList, islossy, unique);
-
- predInfo = (PredInfo*)palloc(sizeof(PredInfo));
- predInfo->pred = predicate;
- predInfo->oldPred = NULL;
-
- /* ----------------
- * initialize the index strategy
- * ----------------
- */
- InitIndexStrategy(numatts, indexRelation, accessMethodObjectId);
-
- /*
- * If this is bootstrap (initdb) time, then we don't actually
- * fill in the index yet. We'll be creating more indices and classes
- * later, so we delay filling them in until just before we're done
- * with bootstrapping. Otherwise, we call the routine that constructs
- * the index. The heap and index relations are closed by index_build().
- */
- if (IsBootstrapProcessingMode()) {
- index_register(heapRelationName, indexRelationName, numatts, attNums,
- parameterCount, parameter, funcInfo, predInfo);
- } else {
- heapRelation = heap_openr(heapRelationName);
- index_build(heapRelation, indexRelation, numatts, attNums,
- parameterCount, parameter, funcInfo, predInfo);
- }
}
/* ----------------------------------------------------------------
- * index_destroy
+ * index_destroy
*
- * XXX break into modules like index_create
+ * XXX break into modules like index_create
* ----------------------------------------------------------------
*/
void
index_destroy(Oid indexId)
{
- Relation indexRelation;
- Relation catalogRelation;
- HeapTuple tuple;
- HeapScanDesc scan;
- ScanKeyData entry;
-
- Assert(OidIsValid(indexId));
-
- indexRelation = index_open(indexId);
-
- /* ----------------
- * fix RELATION relation
- * ----------------
- */
- catalogRelation = heap_openr(RelationRelationName);
-
- ScanKeyEntryInitialize(&entry, 0x0, ObjectIdAttributeNumber,
- ObjectIdEqualRegProcedure,
- ObjectIdGetDatum(indexId));;
-
- scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
- tuple = heap_getnext(scan, 0, (Buffer *)NULL);
-
- AssertState(HeapTupleIsValid(tuple));
-
- heap_delete(catalogRelation, &tuple->t_ctid);
- heap_endscan(scan);
- heap_close(catalogRelation);
-
- /* ----------------
- * fix ATTRIBUTE relation
- * ----------------
- */
- catalogRelation = heap_openr(AttributeRelationName);
-
- entry.sk_attno = Anum_pg_attribute_attrelid;
-
- scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
-
- while (tuple = heap_getnext(scan, 0, (Buffer *)NULL),
- HeapTupleIsValid(tuple)) {
-
+ Relation indexRelation;
+ Relation catalogRelation;
+ HeapTuple tuple;
+ HeapScanDesc scan;
+ ScanKeyData entry;
+
+ Assert(OidIsValid(indexId));
+
+ indexRelation = index_open(indexId);
+
+ /* ----------------
+ * fix RELATION relation
+ * ----------------
+ */
+ catalogRelation = heap_openr(RelationRelationName);
+
+ ScanKeyEntryInitialize(&entry, 0x0, ObjectIdAttributeNumber,
+ ObjectIdEqualRegProcedure,
+ ObjectIdGetDatum(indexId));;
+
+ scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
+ tuple = heap_getnext(scan, 0, (Buffer *) NULL);
+
+ AssertState(HeapTupleIsValid(tuple));
+
+ heap_delete(catalogRelation, &tuple->t_ctid);
+ heap_endscan(scan);
+ heap_close(catalogRelation);
+
+ /* ----------------
+ * fix ATTRIBUTE relation
+ * ----------------
+ */
+ catalogRelation = heap_openr(AttributeRelationName);
+
+ entry.sk_attno = Anum_pg_attribute_attrelid;
+
+ scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
+
+ while (tuple = heap_getnext(scan, 0, (Buffer *) NULL),
+ HeapTupleIsValid(tuple))
+ {
+
+ heap_delete(catalogRelation, &tuple->t_ctid);
+ }
+ heap_endscan(scan);
+ heap_close(catalogRelation);
+
+ /* ----------------
+ * fix INDEX relation
+ * ----------------
+ */
+ catalogRelation = heap_openr(IndexRelationName);
+
+ entry.sk_attno = Anum_pg_index_indexrelid;
+
+ scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
+ tuple = heap_getnext(scan, 0, (Buffer *) NULL);
+ if (!HeapTupleIsValid(tuple))
+ {
+ elog(NOTICE, "IndexRelationDestroy: %s's INDEX tuple missing",
+ RelationGetRelationName(indexRelation));
+ }
heap_delete(catalogRelation, &tuple->t_ctid);
- }
- heap_endscan(scan);
- heap_close(catalogRelation);
-
- /* ----------------
- * fix INDEX relation
- * ----------------
- */
- catalogRelation = heap_openr(IndexRelationName);
-
- entry.sk_attno = Anum_pg_index_indexrelid;
-
- scan = heap_beginscan(catalogRelation, 0, NowTimeQual, 1, &entry);
- tuple = heap_getnext(scan, 0, (Buffer *)NULL);
- if (! HeapTupleIsValid(tuple)) {
- elog(NOTICE, "IndexRelationDestroy: %s's INDEX tuple missing",
- RelationGetRelationName(indexRelation));
- }
- heap_delete(catalogRelation, &tuple->t_ctid);
- heap_endscan(scan);
- heap_close(catalogRelation);
-
- /*
- * physically remove the file
- */
- if (FileNameUnlink(relpath(indexRelation->rd_rel->relname.data)) < 0)
- elog(WARN, "amdestroyr: unlink: %m");
-
- index_close(indexRelation);
+ heap_endscan(scan);
+ heap_close(catalogRelation);
+
+ /*
+ * physically remove the file
+ */
+ if (FileNameUnlink(relpath(indexRelation->rd_rel->relname.data)) < 0)
+ elog(WARN, "amdestroyr: unlink: %m");
+
+ index_close(indexRelation);
}
/* ----------------------------------------------------------------
- * index_build support
+ * index_build support
* ----------------------------------------------------------------
*/
/* ----------------
- * FormIndexDatum
+ * FormIndexDatum
* ----------------
*/
void
FormIndexDatum(int numberOfAttributes,
- AttrNumber attributeNumber[],
- HeapTuple heapTuple,
- TupleDesc heapDescriptor,
- Buffer buffer,
- Datum *datum,
- char *nullv,
- FuncIndexInfoPtr fInfo)
+ AttrNumber attributeNumber[],
+ HeapTuple heapTuple,
+ TupleDesc heapDescriptor,
+ Buffer buffer,
+ Datum * datum,
+ char *nullv,
+ FuncIndexInfoPtr fInfo)
{
- AttrNumber i;
- int offset;
- bool isNull;
-
- /* ----------------
- * for each attribute we need from the heap tuple,
- * get the attribute and stick it into the datum and
- * null arrays.
- * ----------------
- */
-
- for (i = 1; i <= numberOfAttributes; i += 1) {
- offset = AttrNumberGetAttrOffset(i);
-
- datum[ offset ] =
- PointerGetDatum( GetIndexValue(heapTuple,
- heapDescriptor,
- offset,
- attributeNumber,
- fInfo,
- &isNull,
- buffer) );
-
- nullv[ offset ] = (isNull) ? 'n' : ' ';
- }
+ AttrNumber i;
+ int offset;
+ bool isNull;
+
+ /* ----------------
+ * for each attribute we need from the heap tuple,
+ * get the attribute and stick it into the datum and
+ * null arrays.
+ * ----------------
+ */
+
+ for (i = 1; i <= numberOfAttributes; i += 1)
+ {
+ offset = AttrNumberGetAttrOffset(i);
+
+ datum[offset] =
+ PointerGetDatum(GetIndexValue(heapTuple,
+ heapDescriptor,
+ offset,
+ attributeNumber,
+ fInfo,
+ &isNull,
+ buffer));
+
+ nullv[offset] = (isNull) ? 'n' : ' ';
+ }
}
/* ----------------
- * UpdateStats
+ * UpdateStats
* ----------------
*/
void
UpdateStats(Oid relid, long reltuples, bool hasindex)
{
- Relation whichRel;
- Relation pg_class;
- HeapScanDesc pg_class_scan;
- HeapTuple htup;
- HeapTuple newtup;
- long relpages;
- Buffer buffer;
- int i;
- Form_pg_class rd_rel;
- Relation idescs[Num_pg_class_indices];
-
- static ScanKeyData key[1] = {
- { 0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure }
- };
- Datum values[Natts_pg_class];
- char nulls[Natts_pg_class];
- char replace[Natts_pg_class];
-
- fmgr_info(ObjectIdEqualRegProcedure, (func_ptr *) &key[0].sk_func,
- &key[0].sk_nargs);
-
- /* ----------------
- * This routine handles updates for both the heap and index relation
- * statistics. In order to guarantee that we're able to *see* the index
- * relation tuple, we bump the command counter id here. The index
- * relation tuple was created in the current transaction.
- * ----------------
- */
- CommandCounterIncrement();
-
- /* ----------------
- * CommandCounterIncrement() flushes invalid cache entries, including
- * those for the heap and index relations for which we're updating
- * statistics. Now that the cache is flushed, it's safe to open the
- * relation again. We need the relation open in order to figure out
- * how many blocks it contains.
- * ----------------
- */
-
- whichRel = RelationIdGetRelation(relid);
-
- if (!RelationIsValid(whichRel))
- elog(WARN, "UpdateStats: cannot open relation id %d", relid);
-
- /* ----------------
- * Find the RELATION relation tuple for the given relation.
- * ----------------
- */
- pg_class = heap_openr(RelationRelationName);
- if (! RelationIsValid(pg_class)) {
- elog(WARN, "UpdateStats: could not open RELATION relation");
- }
- key[0].sk_argument = ObjectIdGetDatum(relid);
-
- pg_class_scan =
- heap_beginscan(pg_class, 0, NowTimeQual, 1, key);
-
- if (! HeapScanIsValid(pg_class_scan)) {
- heap_close(pg_class);
- elog(WARN, "UpdateStats: cannot scan RELATION relation");
- }
-
- /* if the heap_open above succeeded, then so will this heap_getnext() */
- htup = heap_getnext(pg_class_scan, 0, &buffer);
- heap_endscan(pg_class_scan);
-
- /* ----------------
- * update statistics
- * ----------------
- */
- relpages = RelationGetNumberOfBlocks(whichRel);
-
- /*
- * We shouldn't have to do this, but we do... Modify the reldesc
- * in place with the new values so that the cache contains the
- * latest copy.
- */
-
- whichRel->rd_rel->relhasindex = hasindex;
- whichRel->rd_rel->relpages = relpages;
- whichRel->rd_rel->reltuples = reltuples;
-
- for (i = 0; i < Natts_pg_class; i++) {
- nulls[i] = heap_attisnull(htup, i+1) ? 'n' : ' ';
- replace[i] = ' ';
- values[i] = (Datum) NULL;
- }
-
- /*
- * If reltuples wasn't supplied take an educated guess.
- */
- if (reltuples == 0)
- reltuples = relpages*NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
-
- if (IsBootstrapProcessingMode()) {
-
+ Relation whichRel;
+ Relation pg_class;
+ HeapScanDesc pg_class_scan;
+ HeapTuple htup;
+ HeapTuple newtup;
+ long relpages;
+ Buffer buffer;
+ int i;
+ Form_pg_class rd_rel;
+ Relation idescs[Num_pg_class_indices];
+
+ static ScanKeyData key[1] = {
+ {0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure}
+ };
+ Datum values[Natts_pg_class];
+ char nulls[Natts_pg_class];
+ char replace[Natts_pg_class];
+
+ fmgr_info(ObjectIdEqualRegProcedure, (func_ptr *) & key[0].sk_func,
+ &key[0].sk_nargs);
+
+ /* ----------------
+ * This routine handles updates for both the heap and index relation
+ * statistics. In order to guarantee that we're able to *see* the index
+ * relation tuple, we bump the command counter id here. The index
+ * relation tuple was created in the current transaction.
+ * ----------------
+ */
+ CommandCounterIncrement();
+
+ /* ----------------
+ * CommandCounterIncrement() flushes invalid cache entries, including
+ * those for the heap and index relations for which we're updating
+ * statistics. Now that the cache is flushed, it's safe to open the
+ * relation again. We need the relation open in order to figure out
+ * how many blocks it contains.
+ * ----------------
+ */
+
+ whichRel = RelationIdGetRelation(relid);
+
+ if (!RelationIsValid(whichRel))
+ elog(WARN, "UpdateStats: cannot open relation id %d", relid);
+
+ /* ----------------
+ * Find the RELATION relation tuple for the given relation.
+ * ----------------
+ */
+ pg_class = heap_openr(RelationRelationName);
+ if (!RelationIsValid(pg_class))
+ {
+ elog(WARN, "UpdateStats: could not open RELATION relation");
+ }
+ key[0].sk_argument = ObjectIdGetDatum(relid);
+
+ pg_class_scan =
+ heap_beginscan(pg_class, 0, NowTimeQual, 1, key);
+
+ if (!HeapScanIsValid(pg_class_scan))
+ {
+ heap_close(pg_class);
+ elog(WARN, "UpdateStats: cannot scan RELATION relation");
+ }
+
+ /* if the heap_open above succeeded, then so will this heap_getnext() */
+ htup = heap_getnext(pg_class_scan, 0, &buffer);
+ heap_endscan(pg_class_scan);
+
+ /* ----------------
+ * update statistics
+ * ----------------
+ */
+ relpages = RelationGetNumberOfBlocks(whichRel);
+
+ /*
+ * We shouldn't have to do this, but we do... Modify the reldesc in
+ * place with the new values so that the cache contains the latest
+ * copy.
+ */
+
+ whichRel->rd_rel->relhasindex = hasindex;
+ whichRel->rd_rel->relpages = relpages;
+ whichRel->rd_rel->reltuples = reltuples;
+
+ for (i = 0; i < Natts_pg_class; i++)
+ {
+ nulls[i] = heap_attisnull(htup, i + 1) ? 'n' : ' ';
+ replace[i] = ' ';
+ values[i] = (Datum) NULL;
+ }
+
/*
- * At bootstrap time, we don't need to worry about concurrency
- * or visibility of changes, so we cheat.
- */
-
- rd_rel = (Form_pg_class) GETSTRUCT(htup);
- rd_rel->relpages = relpages;
- rd_rel->reltuples = reltuples;
- rd_rel->relhasindex = hasindex;
- } else {
- /* during normal processing, work harder */
- replace[Anum_pg_class_relpages - 1] = 'r';
- values[Anum_pg_class_relpages - 1] = (Datum)relpages;
- replace[Anum_pg_class_reltuples - 1] = 'r';
- values[Anum_pg_class_reltuples - 1] = (Datum)reltuples;
- replace[Anum_pg_class_relhasindex - 1] = 'r';
- values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
-
- newtup = heap_modifytuple(htup, buffer, pg_class, values,
- nulls, replace);
- heap_replace(pg_class, &(newtup->t_ctid), newtup);
- CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
- CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
- CatalogCloseIndices(Num_pg_class_indices, idescs);
- }
-
- heap_close(pg_class);
- heap_close(whichRel);
+ * If reltuples wasn't supplied take an educated guess.
+ */
+ if (reltuples == 0)
+ reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
+
+ if (IsBootstrapProcessingMode())
+ {
+
+ /*
+ * At bootstrap time, we don't need to worry about concurrency or
+ * visibility of changes, so we cheat.
+ */
+
+ rd_rel = (Form_pg_class) GETSTRUCT(htup);
+ rd_rel->relpages = relpages;
+ rd_rel->reltuples = reltuples;
+ rd_rel->relhasindex = hasindex;
+ }
+ else
+ {
+ /* during normal processing, work harder */
+ replace[Anum_pg_class_relpages - 1] = 'r';
+ values[Anum_pg_class_relpages - 1] = (Datum) relpages;
+ replace[Anum_pg_class_reltuples - 1] = 'r';
+ values[Anum_pg_class_reltuples - 1] = (Datum) reltuples;
+ replace[Anum_pg_class_relhasindex - 1] = 'r';
+ values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
+
+ newtup = heap_modifytuple(htup, buffer, pg_class, values,
+ nulls, replace);
+ heap_replace(pg_class, &(newtup->t_ctid), newtup);
+ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
+ CatalogCloseIndices(Num_pg_class_indices, idescs);
+ }
+
+ heap_close(pg_class);
+ heap_close(whichRel);
}
/* -------------------------
- * FillDummyExprContext
- * Sets up dummy ExprContext and TupleTableSlot objects for use
- * with ExecQual.
+ * FillDummyExprContext
+ * Sets up dummy ExprContext and TupleTableSlot objects for use
+ * with ExecQual.
* -------------------------
*/
void
-FillDummyExprContext(ExprContext *econtext,
- TupleTableSlot *slot,
- TupleDesc tupdesc,
- Buffer buffer)
+FillDummyExprContext(ExprContext * econtext,
+ TupleTableSlot * slot,
+ TupleDesc tupdesc,
+ Buffer buffer)
{
- econtext->ecxt_scantuple = slot;
- econtext->ecxt_innertuple = NULL;
- econtext->ecxt_outertuple = NULL;
- econtext->ecxt_param_list_info = NULL;
- econtext->ecxt_range_table = NULL;
-
- slot->ttc_tupleDescriptor = tupdesc;
- slot->ttc_buffer = buffer;
- slot->ttc_shouldFree = false;
+ econtext->ecxt_scantuple = slot;
+ econtext->ecxt_innertuple = NULL;
+ econtext->ecxt_outertuple = NULL;
+ econtext->ecxt_param_list_info = NULL;
+ econtext->ecxt_range_table = NULL;
+
+ slot->ttc_tupleDescriptor = tupdesc;
+ slot->ttc_buffer = buffer;
+ slot->ttc_shouldFree = false;
}
/* ----------------
- * DefaultBuild
+ * DefaultBuild
* ----------------
*/
static void
DefaultBuild(Relation heapRelation,
- Relation indexRelation,
- int numberOfAttributes,
- AttrNumber attributeNumber[],
- IndexStrategy indexStrategy, /* not used */
- uint16 parameterCount, /* not used */
- Datum parameter[], /* not used */
- FuncIndexInfoPtr funcInfo,
- PredInfo *predInfo)
+ Relation indexRelation,
+ int numberOfAttributes,
+ AttrNumber attributeNumber[],
+ IndexStrategy indexStrategy, /* not used */
+ uint16 parameterCount, /* not used */
+ Datum parameter[], /* not used */
+ FuncIndexInfoPtr funcInfo,
+ PredInfo * predInfo)
{
- HeapScanDesc scan;
- HeapTuple heapTuple;
- Buffer buffer;
-
- IndexTuple indexTuple;
- TupleDesc heapDescriptor;
- TupleDesc indexDescriptor;
- Datum *datum;
- char *nullv;
- long reltuples, indtuples;
+ HeapScanDesc scan;
+ HeapTuple heapTuple;
+ Buffer buffer;
+
+ IndexTuple indexTuple;
+ TupleDesc heapDescriptor;
+ TupleDesc indexDescriptor;
+ Datum *datum;
+ char *nullv;
+ long reltuples,
+ indtuples;
+
#ifndef OMIT_PARTIAL_INDEX
- ExprContext *econtext;
- TupleTable tupleTable;
- TupleTableSlot *slot;
+ ExprContext *econtext;
+ TupleTable tupleTable;
+ TupleTableSlot *slot;
+
#endif
- Node *predicate;
- Node *oldPred;
-
- InsertIndexResult insertResult;
-
- /* ----------------
- * more & better checking is needed
- * ----------------
- */
- Assert(OidIsValid(indexRelation->rd_rel->relam)); /* XXX */
-
- /* ----------------
- * get the tuple descriptors from the relations so we know
- * how to form the index tuples..
- * ----------------
- */
- heapDescriptor = RelationGetTupleDescriptor(heapRelation);
- indexDescriptor = RelationGetTupleDescriptor(indexRelation);
-
- /* ----------------
- * datum and null are arrays in which we collect the index attributes
- * when forming a new index tuple.
- * ----------------
- */
- datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
- nullv = (char *) palloc(numberOfAttributes * sizeof *nullv);
-
- /*
- * If this is a predicate (partial) index, we will need to evaluate the
- * predicate using ExecQual, which requires the current tuple to be in a
- * slot of a TupleTable. In addition, ExecQual must have an ExprContext
- * referring to that slot. Here, we initialize dummy TupleTable and
- * ExprContext objects for this purpose. --Nels, Feb '92
- */
-
- predicate = predInfo->pred;
- oldPred = predInfo->oldPred;
+ Node *predicate;
+ Node *oldPred;
+
+ InsertIndexResult insertResult;
+
+ /* ----------------
+ * more & better checking is needed
+ * ----------------
+ */
+ Assert(OidIsValid(indexRelation->rd_rel->relam)); /* XXX */
+
+ /* ----------------
+ * get the tuple descriptors from the relations so we know
+ * how to form the index tuples..
+ * ----------------
+ */
+ heapDescriptor = RelationGetTupleDescriptor(heapRelation);
+ indexDescriptor = RelationGetTupleDescriptor(indexRelation);
+
+ /* ----------------
+ * datum and null are arrays in which we collect the index attributes
+ * when forming a new index tuple.
+ * ----------------
+ */
+ datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
+ nullv = (char *) palloc(numberOfAttributes * sizeof *nullv);
+
+ /*
+ * If this is a predicate (partial) index, we will need to evaluate
+ * the predicate using ExecQual, which requires the current tuple to
+ * be in a slot of a TupleTable. In addition, ExecQual must have an
+ * ExprContext referring to that slot. Here, we initialize dummy
+ * TupleTable and ExprContext objects for this purpose. --Nels, Feb
+ * '92
+ */
+
+ predicate = predInfo->pred;
+ oldPred = predInfo->oldPred;
#ifndef OMIT_PARTIAL_INDEX
- if (predicate != NULL || oldPred != NULL) {
- tupleTable = ExecCreateTupleTable(1);
- slot = ExecAllocTableSlot(tupleTable);
- econtext = makeNode(ExprContext);
- FillDummyExprContext(econtext, slot, heapDescriptor, buffer);
- }
+ if (predicate != NULL || oldPred != NULL)
+ {
+ tupleTable = ExecCreateTupleTable(1);
+ slot = ExecAllocTableSlot(tupleTable);
+ econtext = makeNode(ExprContext);
+ FillDummyExprContext(econtext, slot, heapDescriptor, buffer);
+ }
else
{
econtext = NULL;
tupleTable = 0;
slot = NULL;
}
-#endif /* OMIT_PARTIAL_INDEX */
-
- /* ----------------
- * Ok, begin our scan of the base relation.
- * ----------------
- */
- scan = heap_beginscan(heapRelation, /* relation */
- 0, /* start at end */
- NowTimeQual, /* time range */
- 0, /* number of keys */
- (ScanKey) NULL); /* scan key */
-
- reltuples = indtuples = 0;
-
- /* ----------------
- * for each tuple in the base relation, we create an index
- * tuple and add it to the index relation. We keep a running
- * count of the number of tuples so that we can update pg_class
- * with correct statistics when we're done building the index.
- * ----------------
- */
- while (heapTuple = heap_getnext(scan, 0, &buffer),
- HeapTupleIsValid(heapTuple)) {
-
- reltuples++;
-
- /*
- * If oldPred != NULL, this is an EXTEND INDEX command, so skip
- * this tuple if it was already in the existing partial index
+#endif /* OMIT_PARTIAL_INDEX */
+
+ /* ----------------
+ * Ok, begin our scan of the base relation.
+ * ----------------
*/
- if (oldPred != NULL) {
+ scan = heap_beginscan(heapRelation, /* relation */
+ 0, /* start at end */
+ NowTimeQual, /* time range */
+ 0, /* number of keys */
+ (ScanKey) NULL); /* scan key */
+
+ reltuples = indtuples = 0;
+
+ /* ----------------
+ * for each tuple in the base relation, we create an index
+ * tuple and add it to the index relation. We keep a running
+ * count of the number of tuples so that we can update pg_class
+ * with correct statistics when we're done building the index.
+ * ----------------
+ */
+ while (heapTuple = heap_getnext(scan, 0, &buffer),
+ HeapTupleIsValid(heapTuple))
+ {
+
+ reltuples++;
+
+ /*
+ * If oldPred != NULL, this is an EXTEND INDEX command, so skip
+ * this tuple if it was already in the existing partial index
+ */
+ if (oldPred != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*SetSlotContents(slot, heapTuple); */
- slot->val = heapTuple;
- if (ExecQual((List*)oldPred, econtext) == true) {
+ /* SetSlotContents(slot, heapTuple); */
+ slot->val = heapTuple;
+ if (ExecQual((List *) oldPred, econtext) == true)
+ {
+ indtuples++;
+ continue;
+ }
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
+ /*
+ * Skip this tuple if it doesn't satisfy the partial-index
+ * predicate
+ */
+ if (predicate != NULL)
+ {
+#ifndef OMIT_PARTIAL_INDEX
+ /* SetSlotContents(slot, heapTuple); */
+ slot->val = heapTuple;
+ if (ExecQual((List *) predicate, econtext) == false)
+ continue;
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+
indtuples++;
- continue;
- }
-#endif /* OMIT_PARTIAL_INDEX */
+
+ /* ----------------
+ * FormIndexDatum fills in its datum and null parameters
+ * with attribute information taken from the given heap tuple.
+ * ----------------
+ */
+ FormIndexDatum(numberOfAttributes, /* num attributes */
+ attributeNumber, /* array of att nums to extract */
+ heapTuple, /* tuple from base relation */
+ heapDescriptor, /* heap tuple's descriptor */
+ buffer, /* buffer used in the scan */
+ datum, /* return: array of attributes */
+ nullv, /* return: array of char's */
+ funcInfo);
+
+ indexTuple = index_formtuple(indexDescriptor,
+ datum,
+ nullv);
+
+ indexTuple->t_tid = heapTuple->t_ctid;
+
+ insertResult = index_insert(indexRelation, datum, nullv,
+ &(heapTuple->t_ctid), heapRelation);
+
+ if (insertResult)
+ pfree(insertResult);
+ pfree(indexTuple);
}
-
- /* Skip this tuple if it doesn't satisfy the partial-index predicate */
- if (predicate != NULL) {
+
+ heap_endscan(scan);
+
+ if (predicate != NULL || oldPred != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*SetSlotContents(slot, heapTuple); */
- slot->val = heapTuple;
- if (ExecQual((List*)predicate, econtext) == false)
- continue;
-#endif /* OMIT_PARTIAL_INDEX */
+ ExecDestroyTupleTable(tupleTable, false);
+#endif /* OMIT_PARTIAL_INDEX */
}
-
- indtuples++;
-
- /* ----------------
- * FormIndexDatum fills in its datum and null parameters
- * with attribute information taken from the given heap tuple.
- * ----------------
+
+ pfree(nullv);
+ pfree(datum);
+
+ /*
+ * Okay, now update the reltuples and relpages statistics for both the
+ * heap relation and the index. These statistics are used by the
+ * planner to choose a scan type. They are maintained generally by
+ * the vacuum daemon, but we update them here to make the index useful
+ * as soon as possible.
*/
- FormIndexDatum(numberOfAttributes, /* num attributes */
- attributeNumber, /* array of att nums to extract */
- heapTuple, /* tuple from base relation */
- heapDescriptor, /* heap tuple's descriptor */
- buffer, /* buffer used in the scan */
- datum, /* return: array of attributes */
- nullv, /* return: array of char's */
- funcInfo);
-
- indexTuple = index_formtuple(indexDescriptor,
- datum,
- nullv);
-
- indexTuple->t_tid = heapTuple->t_ctid;
-
- insertResult = index_insert(indexRelation, datum, nullv,
- &(heapTuple->t_ctid), heapRelation);
-
- if (insertResult) pfree(insertResult);
- pfree(indexTuple);
- }
-
- heap_endscan(scan);
-
- if (predicate != NULL || oldPred != NULL) {
-#ifndef OMIT_PARTIAL_INDEX
- ExecDestroyTupleTable(tupleTable, false);
-#endif /* OMIT_PARTIAL_INDEX */
- }
-
- pfree(nullv);
- pfree(datum);
-
- /*
- * Okay, now update the reltuples and relpages statistics for both
- * the heap relation and the index. These statistics are used by
- * the planner to choose a scan type. They are maintained generally
- * by the vacuum daemon, but we update them here to make the index
- * useful as soon as possible.
- */
- UpdateStats(heapRelation->rd_id, reltuples, true);
- UpdateStats(indexRelation->rd_id, indtuples, false);
- if (oldPred != NULL) {
- if (indtuples == reltuples) predicate = NULL;
- UpdateIndexPredicate(indexRelation->rd_id, oldPred, predicate);
- }
+ UpdateStats(heapRelation->rd_id, reltuples, true);
+ UpdateStats(indexRelation->rd_id, indtuples, false);
+ if (oldPred != NULL)
+ {
+ if (indtuples == reltuples)
+ predicate = NULL;
+ UpdateIndexPredicate(indexRelation->rd_id, oldPred, predicate);
+ }
}
/* ----------------
- * index_build
+ * index_build
* ----------------
*/
void
index_build(Relation heapRelation,
- Relation indexRelation,
- int numberOfAttributes,
- AttrNumber attributeNumber[],
- uint16 parameterCount,
- Datum *parameter,
- FuncIndexInfo *funcInfo,
- PredInfo *predInfo)
+ Relation indexRelation,
+ int numberOfAttributes,
+ AttrNumber attributeNumber[],
+ uint16 parameterCount,
+ Datum * parameter,
+ FuncIndexInfo * funcInfo,
+ PredInfo * predInfo)
{
- RegProcedure procedure;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(RelationIsValid(indexRelation));
- Assert(PointerIsValid(indexRelation->rd_am));
-
- procedure = indexRelation->rd_am->ambuild;
-
- /* ----------------
- * use the access method build procedure if supplied..
- * ----------------
- */
- if (RegProcedureIsValid(procedure))
- fmgr(procedure,
- heapRelation,
- indexRelation,
- numberOfAttributes,
- attributeNumber,
- RelationGetIndexStrategy(indexRelation),
- parameterCount,
- parameter,
- funcInfo,
- predInfo);
- else
- DefaultBuild(heapRelation,
- indexRelation,
- numberOfAttributes,
- attributeNumber,
- RelationGetIndexStrategy(indexRelation),
- parameterCount,
- parameter,
- funcInfo,
- predInfo);
+ RegProcedure procedure;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ Assert(RelationIsValid(indexRelation));
+ Assert(PointerIsValid(indexRelation->rd_am));
+
+ procedure = indexRelation->rd_am->ambuild;
+
+ /* ----------------
+ * use the access method build procedure if supplied..
+ * ----------------
+ */
+ if (RegProcedureIsValid(procedure))
+ fmgr(procedure,
+ heapRelation,
+ indexRelation,
+ numberOfAttributes,
+ attributeNumber,
+ RelationGetIndexStrategy(indexRelation),
+ parameterCount,
+ parameter,
+ funcInfo,
+ predInfo);
+ else
+ DefaultBuild(heapRelation,
+ indexRelation,
+ numberOfAttributes,
+ attributeNumber,
+ RelationGetIndexStrategy(indexRelation),
+ parameterCount,
+ parameter,
+ funcInfo,
+ predInfo);
}
/*
@@ -1712,20 +1781,21 @@ index_build(Relation heapRelation,
bool
IndexIsUnique(Oid indexId)
{
- HeapTuple tuple;
- IndexTupleForm index;
-
- tuple = SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(indexId),
- 0,0,0);
- if(!HeapTupleIsValid(tuple)) {
- elog(WARN, "IndexIsUnique: can't find index id %d",
- indexId);
- }
- index = (IndexTupleForm)GETSTRUCT(tuple);
- Assert(index->indexrelid == indexId);
-
- return index->indisunique;
+ HeapTuple tuple;
+ IndexTupleForm index;
+
+ tuple = SearchSysCacheTuple(INDEXRELID,
+ ObjectIdGetDatum(indexId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ {
+ elog(WARN, "IndexIsUnique: can't find index id %d",
+ indexId);
+ }
+ index = (IndexTupleForm) GETSTRUCT(tuple);
+ Assert(index->indexrelid == indexId);
+
+ return index->indisunique;
}
/*
@@ -1743,32 +1813,33 @@ IndexIsUnique(Oid indexId)
bool
IndexIsUniqueNoCache(Oid indexId)
{
- Relation pg_index;
- ScanKeyData skey[1];
- HeapScanDesc scandesc;
- HeapTuple tuple;
- IndexTupleForm index;
- bool isunique;
-
- pg_index = heap_openr(IndexRelationName);
-
- ScanKeyEntryInitialize(&skey[0], (bits16)0x0,
- Anum_pg_index_indexrelid,
- (RegProcedure)ObjectIdEqualRegProcedure,
- ObjectIdGetDatum(indexId));
-
- scandesc = heap_beginscan(pg_index, 0, SelfTimeQual, 1, skey);
-
- tuple = heap_getnext(scandesc, 0, NULL);
- if(!HeapTupleIsValid(tuple)) {
- elog(WARN, "IndexIsUniqueNoCache: can't find index id %d",
- indexId);
- }
- index = (IndexTupleForm)GETSTRUCT(tuple);
- Assert(index->indexrelid == indexId);
- isunique = index->indisunique;
-
- heap_endscan (scandesc);
- heap_close (pg_index);
- return isunique;
+ Relation pg_index;
+ ScanKeyData skey[1];
+ HeapScanDesc scandesc;
+ HeapTuple tuple;
+ IndexTupleForm index;
+ bool isunique;
+
+ pg_index = heap_openr(IndexRelationName);
+
+ ScanKeyEntryInitialize(&skey[0], (bits16) 0x0,
+ Anum_pg_index_indexrelid,
+ (RegProcedure) ObjectIdEqualRegProcedure,
+ ObjectIdGetDatum(indexId));
+
+ scandesc = heap_beginscan(pg_index, 0, SelfTimeQual, 1, skey);
+
+ tuple = heap_getnext(scandesc, 0, NULL);
+ if (!HeapTupleIsValid(tuple))
+ {
+ elog(WARN, "IndexIsUniqueNoCache: can't find index id %d",
+ indexId);
+ }
+ index = (IndexTupleForm) GETSTRUCT(tuple);
+ Assert(index->indexrelid == indexId);
+ isunique = index->indisunique;
+
+ heap_endscan(scandesc);
+ heap_close(pg_index);
+ return isunique;
}