aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/cluster.c66
-rw-r--r--src/backend/commands/command.c21
-rw-r--r--src/backend/commands/copy.c241
-rw-r--r--src/backend/commands/indexcmds.c312
-rw-r--r--src/backend/commands/vacuum.c110
5 files changed, 242 insertions, 508 deletions
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 38539707cd8..5c176254d66 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.57 2000/07/04 06:11:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.58 2000/07/14 22:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -198,35 +198,31 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
Relation OldIndex,
NewHeap;
HeapTuple Old_pg_index_Tuple,
- Old_pg_index_relation_Tuple,
- pg_proc_Tuple;
+ Old_pg_index_relation_Tuple;
Form_pg_index Old_pg_index_Form;
Form_pg_class Old_pg_index_relation_Form;
- Form_pg_proc pg_proc_Form;
+ IndexInfo *indexInfo;
char *NewIndexName;
- AttrNumber *attnumP;
- int natts;
- FuncIndexInfo *finfo;
NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldIndex = index_open(OIDOldIndex);
/*
* OK. Create a new (temporary) index for the one that's already here.
- * To do this I get the info from pg_index, re-build the FunctInfo if
- * I have to, and add a new index with a temporary name.
+ * To do this I get the info from pg_index, and add a new index with
+ * a temporary name.
*/
- Old_pg_index_Tuple = SearchSysCacheTuple(INDEXRELID,
+ Old_pg_index_Tuple = SearchSysCacheTupleCopy(INDEXRELID,
ObjectIdGetDatum(RelationGetRelid(OldIndex)),
- 0, 0, 0);
-
+ 0, 0, 0);
Assert(Old_pg_index_Tuple);
Old_pg_index_Form = (Form_pg_index) GETSTRUCT(Old_pg_index_Tuple);
- Old_pg_index_relation_Tuple = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(RelationGetRelid(OldIndex)),
- 0, 0, 0);
+ indexInfo = BuildIndexInfo(Old_pg_index_Tuple);
+ Old_pg_index_relation_Tuple = SearchSysCacheTupleCopy(RELOID,
+ ObjectIdGetDatum(RelationGetRelid(OldIndex)),
+ 0, 0, 0);
Assert(Old_pg_index_relation_Tuple);
Old_pg_index_relation_Form = (Form_pg_class) GETSTRUCT(Old_pg_index_relation_Tuple);
@@ -234,50 +230,12 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
NewIndexName = palloc(NAMEDATALEN); /* XXX */
snprintf(NewIndexName, NAMEDATALEN, "temp_%x", OIDOldIndex);
- /*
- * Ugly as it is, the only way I have of working out the number of
- * attribues is to count them. Mostly there'll be just one but I've
- * got to be sure.
- */
- for (attnumP = &(Old_pg_index_Form->indkey[0]), natts = 0;
- natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber;
- attnumP++, natts++);
-
- /*
- * If this is a functional index, I need to rebuild the functional
- * component to pass it to the defining procedure.
- */
- if (Old_pg_index_Form->indproc != InvalidOid)
- {
- finfo = (FuncIndexInfo *) palloc(sizeof(FuncIndexInfo));
- FIgetnArgs(finfo) = natts;
- FIgetProcOid(finfo) = Old_pg_index_Form->indproc;
-
- pg_proc_Tuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(Old_pg_index_Form->indproc),
- 0, 0, 0);
-
- Assert(pg_proc_Tuple);
- pg_proc_Form = (Form_pg_proc) GETSTRUCT(pg_proc_Tuple);
- namecpy(&(finfo->funcName), &(pg_proc_Form->proname));
- natts = 1; /* function result is a single column */
- }
- else
- {
- finfo = (FuncIndexInfo *) NULL;
- }
-
index_create(RelationGetRelationName(NewHeap),
NewIndexName,
- finfo,
- NULL, /* type info is in the old index */
+ indexInfo,
Old_pg_index_relation_Form->relam,
- natts,
- Old_pg_index_Form->indkey,
Old_pg_index_Form->indclass,
- (Node *) NULL, /* XXX where's the predicate? */
Old_pg_index_Form->indislossy,
- Old_pg_index_Form->indisunique,
Old_pg_index_Form->indisprimary,
allowSystemTableMods);
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 6648e66f4e3..be24c696a7c 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.88 2000/07/05 23:11:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.89 2000/07/14 22:17:42 tgl Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
@@ -1205,7 +1205,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
char toast_relname[NAMEDATALEN + 1];
char toast_idxname[NAMEDATALEN + 1];
Relation toast_rel;
- AttrNumber attNums[1];
+ IndexInfo *indexInfo;
Oid classObjectId[1];
/*
@@ -1334,11 +1334,20 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
CommandCounterIncrement();
/* create index on chunk_id */
- attNums[0] = 1;
+
+ indexInfo = makeNode(IndexInfo);
+ indexInfo->ii_NumIndexAttrs = 1;
+ indexInfo->ii_NumKeyAttrs = 1;
+ indexInfo->ii_KeyAttrNumbers[0] = 1;
+ indexInfo->ii_Predicate = NULL;
+ indexInfo->ii_FuncOid = InvalidOid;
+ indexInfo->ii_Unique = false;
+
classObjectId[0] = OID_OPS_OID;
- index_create(toast_relname, toast_idxname, NULL, NULL, BTREE_AM_OID,
- 1, attNums, classObjectId,
- (Node *) NULL, false, false, false, true);
+
+ index_create(toast_relname, toast_idxname, indexInfo,
+ BTREE_AM_OID, classObjectId,
+ false, false, true);
/* make the index visible in this transaction */
CommandCounterIncrement();
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 355b218e640..52100e92dd9 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.118 2000/07/12 02:36:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.119 2000/07/14 22:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -50,10 +50,6 @@ static Oid GetOutputFunction(Oid type);
static Oid GetTypeElement(Oid type);
static Oid GetInputFunction(Oid type);
static Oid IsTypeByVal(Oid type);
-static void GetIndexRelations(Oid main_relation_oid,
- int *n_indices,
- Relation **index_rels);
-
static void CopyReadNewline(FILE *fp, int *newline);
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print);
@@ -576,53 +572,35 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_p
}
static void
-CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print)
+CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
+ char *delim, char *null_print)
{
HeapTuple tuple;
- AttrNumber attr_count;
+ TupleDesc tupDesc;
Form_pg_attribute *attr;
+ AttrNumber attr_count;
FmgrInfo *in_functions;
+ Oid *elements;
+ int32 *typmod;
int i;
Oid in_func_oid;
Datum *values;
- char *nulls,
- *index_nulls;
+ char *nulls;
bool *byval;
bool isnull;
- bool has_index;
int done = 0;
char *string = NULL,
*ptr;
- Relation *index_rels;
int32 len,
null_ct,
null_id;
int32 ntuples,
tuples_read = 0;
bool reading_to_eof = true;
- Oid *elements;
- int32 *typmod;
- FuncIndexInfo *finfo,
- **finfoP = NULL;
- TupleDesc *itupdescArr;
- HeapTuple pgIndexTup;
- Form_pg_index *pgIndexP = NULL;
- int *indexNatts = NULL;
- char *predString;
- Node **indexPred = NULL;
- TupleDesc rtupdesc;
+ RelationInfo *relationInfo;
EState *estate = makeNode(EState); /* for ExecConstraints() */
-#ifndef OMIT_PARTIAL_INDEX
- ExprContext *econtext = NULL;
TupleTable tupleTable;
- TupleTableSlot *slot = NULL;
-#endif
- int natts;
- AttrNumber *attnumP;
- Datum *idatum;
- int n_indices;
- InsertIndexResult indexRes;
- TupleDesc tupDesc;
+ TupleTableSlot *slot;
Oid loaded_oid = InvalidOid;
bool skip_tuple = false;
@@ -630,71 +608,26 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
attr = tupDesc->attrs;
attr_count = tupDesc->natts;
- has_index = false;
-
/*
- * This may be a scalar or a functional index. We initialize all
- * kinds of arrays here to avoid doing extra work at every tuple copy.
+ * We need a RelationInfo so we can use the regular executor's
+ * index-entry-making machinery. (There used to be a huge amount
+ * of code here that basically duplicated execUtils.c ...)
*/
+ relationInfo = makeNode(RelationInfo);
+ relationInfo->ri_RangeTableIndex = 1; /* dummy */
+ relationInfo->ri_RelationDesc = rel;
+ relationInfo->ri_NumIndices = 0;
+ relationInfo->ri_IndexRelationDescs = NULL;
+ relationInfo->ri_IndexRelationInfo = NULL;
- if (rel->rd_rel->relhasindex)
- {
- GetIndexRelations(RelationGetRelid(rel), &n_indices, &index_rels);
- if (n_indices > 0)
- {
- has_index = true;
- itupdescArr = (TupleDesc *) palloc(n_indices * sizeof(TupleDesc));
- pgIndexP = (Form_pg_index *) palloc(n_indices * sizeof(Form_pg_index));
- indexNatts = (int *) palloc(n_indices * sizeof(int));
- finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo));
- finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *));
- indexPred = (Node **) palloc(n_indices * sizeof(Node *));
- for (i = 0; i < n_indices; i++)
- {
- itupdescArr[i] = RelationGetDescr(index_rels[i]);
- pgIndexTup = SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(RelationGetRelid(index_rels[i])),
- 0, 0, 0);
- Assert(pgIndexTup);
- pgIndexP[i] = (Form_pg_index) GETSTRUCT(pgIndexTup);
- for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0;
- natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber;
- attnumP++, natts++);
- if (pgIndexP[i]->indproc != InvalidOid)
- {
- FIgetnArgs(&finfo[i]) = natts;
- natts = 1;
- FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc;
- *(FIgetname(&finfo[i])) = '\0';
- finfoP[i] = &finfo[i];
- }
- else
- finfoP[i] = (FuncIndexInfo *) NULL;
- indexNatts[i] = natts;
- if (VARSIZE(&pgIndexP[i]->indpred) != 0)
- {
- predString = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(&pgIndexP[i]->indpred)));
- indexPred[i] = stringToNode(predString);
- pfree(predString);
-#ifndef OMIT_PARTIAL_INDEX
- /* make dummy ExprContext for use by ExecQual */
- if (econtext == NULL)
- {
- tupleTable = ExecCreateTupleTable(1);
- slot = ExecAllocTableSlot(tupleTable);
- rtupdesc = RelationGetDescr(rel);
- ExecSetSlotDescriptor(slot, rtupdesc);
- econtext = MakeExprContext(slot,
- TransactionCommandContext);
- }
-#endif /* OMIT_PARTIAL_INDEX */
- }
- else
- indexPred[i] = NULL;
- }
- }
- }
+ ExecOpenIndices(relationInfo);
+
+ estate->es_result_relation_info = relationInfo;
+
+ /* Set up a dummy tuple table too */
+ tupleTable = ExecCreateTupleTable(1);
+ slot = ExecAllocTableSlot(tupleTable);
+ ExecSetSlotDescriptor(slot, tupDesc);
if (!binary)
{
@@ -723,16 +656,13 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
reading_to_eof = false;
}
- values = (Datum *) palloc(sizeof(Datum) * attr_count);
- nulls = (char *) palloc(attr_count);
- index_nulls = (char *) palloc(attr_count);
- idatum = (Datum *) palloc(sizeof(Datum) * attr_count);
+ values = (Datum *) palloc(attr_count * sizeof(Datum));
+ nulls = (char *) palloc(attr_count * sizeof(char));
byval = (bool *) palloc(attr_count * sizeof(bool));
for (i = 0; i < attr_count; i++)
{
nulls[i] = ' ';
- index_nulls[i] = ' ';
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
{
@@ -873,6 +803,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
tuple->t_data->t_oid = loaded_oid;
skip_tuple = false;
+
/* BEFORE ROW INSERT Triggers */
if (rel->trigdesc &&
rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
@@ -893,45 +824,25 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
if (!skip_tuple)
{
/* ----------------
- * Check the constraints of a tuple
+ * Check the constraints of the tuple
* ----------------
*/
if (rel->rd_att->constr)
ExecConstraints("CopyFrom", rel, tuple, estate);
+ /* ----------------
+ * OK, store the tuple and create index entries for it
+ * ----------------
+ */
heap_insert(rel, tuple);
- if (has_index)
+ if (relationInfo->ri_NumIndices > 0)
{
- for (i = 0; i < n_indices; i++)
- {
-#ifndef OMIT_PARTIAL_INDEX
- if (indexPred[i] != NULL)
- {
- /*
- * if tuple doesn't satisfy predicate, don't
- * update index
- */
- slot->val = tuple;
- /* SetSlotContents(slot, tuple); */
- if (!ExecQual((List *) indexPred[i], econtext, false))
- continue;
- }
-#endif /* OMIT_PARTIAL_INDEX */
- FormIndexDatum(indexNatts[i],
- (AttrNumber *) &(pgIndexP[i]->indkey[0]),
- tuple,
- tupDesc,
- idatum,
- index_nulls,
- finfoP[i]);
- indexRes = index_insert(index_rels[i], idatum, index_nulls,
- &(tuple->t_self), rel);
- if (indexRes)
- pfree(indexRes);
- }
+ ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
}
+
/* AFTER ROW INSERT Triggers */
if (rel->trigdesc &&
rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
@@ -948,8 +859,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
if (!binary)
pfree((void *) values[i]);
}
- else if (nulls[i] == 'n')
- nulls[i] = ' ';
+ /* reset nulls[] array for next time */
+ nulls[i] = ' ';
}
heap_freetuple(tuple);
@@ -958,11 +869,14 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
if (!reading_to_eof && ntuples == tuples_read)
done = true;
}
+
+ /*
+ * Done, clean up
+ */
lineno = 0;
+
pfree(values);
pfree(nulls);
- pfree(index_nulls);
- pfree(idatum);
pfree(byval);
if (!binary)
@@ -972,21 +886,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
pfree(typmod);
}
- if (has_index)
- {
- for (i = 0; i < n_indices; i++)
- {
- if (index_rels[i] == NULL)
- continue;
- /* see comments in ExecOpenIndices() in execUtils.c */
- if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
- (index_rels[i])->rd_rel->relam != HASH_AM_OID)
- UnlockRelation(index_rels[i], AccessExclusiveLock);
- index_close(index_rels[i]);
- }
- }
-}
+ ExecDropTupleTable(tupleTable, true);
+ ExecCloseIndices(relationInfo);
+}
static Oid
@@ -1054,52 +957,6 @@ IsTypeByVal(Oid type)
return InvalidOid;
}
-/*
- * Given the OID of a relation, return an array of index relation descriptors
- * and the number of index relations. These relation descriptors are open
- * using index_open().
- *
- * Space for the array itself is palloc'ed.
- */
-
-static void
-GetIndexRelations(Oid main_relation_oid,
- int *n_indices,
- Relation **index_rels)
-{
- Relation relation;
- List *indexoidlist,
- *indexoidscan;
- int i;
-
- relation = heap_open(main_relation_oid, AccessShareLock);
- indexoidlist = RelationGetIndexList(relation);
-
- *n_indices = length(indexoidlist);
-
- if (*n_indices > 0)
- *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
- else
- *index_rels = NULL;
-
- i = 0;
- foreach(indexoidscan, indexoidlist)
- {
- Oid indexoid = lfirsti(indexoidscan);
- Relation index = index_open(indexoid);
-
- /* see comments in ExecOpenIndices() in execUtils.c */
- if (index != NULL &&
- index->rd_rel->relam != BTREE_AM_OID &&
- index->rd_rel->relam != HASH_AM_OID)
- LockRelation(index, AccessExclusiveLock);
- (*index_rels)[i] = index;
- i++;
- }
-
- freeList(indexoidlist);
- heap_close(relation, AccessShareLock);
-}
/*
* Reads input from fp until an end of line is seen.
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index efe8a44180a..6ede4f51c12 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.34 2000/07/05 23:11:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.35 2000/07/14 22:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/index.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_database.h"
#include "catalog/pg_index.h"
@@ -47,14 +48,14 @@
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
-static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
- AttrNumber *attNumP, Oid *opOidP, Oid relId,
+static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP,
+ IndexElem *funcIndex,
+ Oid relId,
char *accessMethodName, Oid accessMethodId);
-static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
- Oid *opOidP, Oid relId,
+static void NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP,
+ List *attList,
+ Oid relId,
char *accessMethodName, Oid accessMethodId);
-static void ProcessAttrTypename(IndexElem *attribute,
- Oid defType, int32 defTypmod);
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType,
char *accessMethodName, Oid accessMethodId);
static char *GetDefaultOpClass(Oid atttypid);
@@ -67,10 +68,7 @@ static char *GetDefaultOpClass(Oid atttypid);
* index or a list of attributes to index on.
* 'parameterList' is a list of DefElem specified in the with clause.
* 'predicate' is the qual specified in the where clause.
- * 'rangetable' is for the predicate
- *
- * Exceptions:
- * XXX
+ * 'rangetable' is needed to interpret the predicate
*/
void
DefineIndex(char *heapRelationName,
@@ -86,16 +84,15 @@ DefineIndex(char *heapRelationName,
Oid *classObjectId;
Oid accessMethodId;
Oid relationId;
+ IndexInfo *indexInfo;
int numberOfAttributes;
- AttrNumber *attributeNumberA;
HeapTuple tuple;
- FuncIndexInfo fInfo;
- List *cnfPred = NULL;
+ List *cnfPred = NIL;
bool lossy = false;
List *pl;
/*
- * count attributes
+ * count attributes in index
*/
numberOfAttributes = length(attributeList);
if (numberOfAttributes <= 0)
@@ -108,21 +105,8 @@ DefineIndex(char *heapRelationName,
* compute heap relation id
*/
if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid)
- {
elog(ERROR, "DefineIndex: relation \"%s\" not found",
heapRelationName);
- }
-
- /*
- * XXX Hardwired hacks to check for limitations on supported index types.
- * We really ought to be learning this info from entries in the pg_am
- * table, instead of having it wired in here!
- */
- if (unique && strcmp(accessMethodName, "btree") != 0)
- elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
-
- if (numberOfAttributes > 1 && strcmp(accessMethodName, "btree") != 0)
- elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method");
/*
* compute access method id
@@ -131,13 +115,22 @@ DefineIndex(char *heapRelationName,
PointerGetDatum(accessMethodName),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- {
elog(ERROR, "DefineIndex: access method \"%s\" not found",
accessMethodName);
- }
accessMethodId = tuple->t_data->t_oid;
/*
+ * XXX Hardwired hacks to check for limitations on supported index types.
+ * We really ought to be learning this info from entries in the pg_am
+ * table, instead of having it wired in here!
+ */
+ if (unique && accessMethodId != BTREE_AM_OID)
+ elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
+
+ if (numberOfAttributes > 1 && accessMethodId != BTREE_AM_OID)
+ elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method");
+
+ /*
* WITH clause reinstated to handle lossy indices. -- JMH, 7/22/96
*/
foreach(pl, parameterList)
@@ -145,7 +138,7 @@ DefineIndex(char *heapRelationName,
DefElem *param = (DefElem *) lfirst(pl);
if (!strcasecmp(param->defname, "islossy"))
- lossy = TRUE;
+ lossy = true;
else
elog(NOTICE, "Unrecognized index attribute \"%s\" ignored",
param->defname);
@@ -169,55 +162,51 @@ DefineIndex(char *heapRelationName,
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
elog(ERROR, "Existing indexes are inactive. REINDEX first");
+ /*
+ * Prepare arguments for index_create, primarily an IndexInfo structure
+ */
+ indexInfo = makeNode(IndexInfo);
+ indexInfo->ii_Predicate = (Node *) cnfPred;
+ indexInfo->ii_FuncOid = InvalidOid;
+ indexInfo->ii_Unique = unique;
+
if (IsFuncIndex(attributeList))
{
- IndexElem *funcIndex = lfirst(attributeList);
+ IndexElem *funcIndex = (IndexElem *) lfirst(attributeList);
int nargs;
+ /* Parser should have given us only one list item, but check */
+ if (numberOfAttributes != 1)
+ elog(ERROR, "Functional index can only have one attribute");
+
nargs = length(funcIndex->args);
if (nargs > INDEX_MAX_KEYS)
elog(ERROR, "Index function can take at most %d arguments",
INDEX_MAX_KEYS);
- FIsetnArgs(&fInfo, nargs);
-
- namestrcpy(&fInfo.funcName, funcIndex->name);
-
- attributeNumberA = (AttrNumber *) palloc(nargs *
- sizeof attributeNumberA[0]);
+ indexInfo->ii_NumIndexAttrs = 1;
+ indexInfo->ii_NumKeyAttrs = nargs;
classObjectId = (Oid *) palloc(sizeof(Oid));
- FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
- classObjectId, relationId,
- accessMethodName, accessMethodId);
-
- index_create(heapRelationName, indexRelationName,
- &fInfo, NULL,
- accessMethodId, numberOfAttributes, attributeNumberA,
- classObjectId,
- (Node *) cnfPred,
- lossy, unique, primary, allowSystemTableMods);
+ FuncIndexArgs(indexInfo, classObjectId, funcIndex,
+ relationId, accessMethodName, accessMethodId);
}
else
{
- attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
- sizeof attributeNumberA[0]);
+ indexInfo->ii_NumIndexAttrs = numberOfAttributes;
+ indexInfo->ii_NumKeyAttrs = numberOfAttributes;
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
- NormIndexAttrs(attributeList, attributeNumberA,
- classObjectId, relationId,
- accessMethodName, accessMethodId);
-
- index_create(heapRelationName, indexRelationName,
- NULL, attributeList,
- accessMethodId, numberOfAttributes, attributeNumberA,
- classObjectId,
- (Node *) cnfPred,
- lossy, unique, primary, allowSystemTableMods);
+ NormIndexAttrs(indexInfo, classObjectId, attributeList,
+ relationId, accessMethodName, accessMethodId);
}
+ index_create(heapRelationName, indexRelationName,
+ indexInfo, accessMethodId, classObjectId,
+ lossy, primary, allowSystemTableMods);
+
/*
* We update the relation's pg_class tuple even if it already has
* relhasindex = true. This is needed to cause a shared-cache-inval
@@ -232,83 +221,48 @@ DefineIndex(char *heapRelationName,
/*
* ExtendIndex
* Extends a partial index.
- *
- * Exceptions:
- * XXX
*/
void
ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
{
- Oid *classObjectId;
- Oid accessMethodId;
- Oid indexId,
+ Relation heapRelation;
+ Relation indexRelation;
+ Oid accessMethodId,
+ indexId,
relationId;
- Oid indproc;
- int numberOfAttributes;
- AttrNumber *attributeNumberA;
HeapTuple tuple;
- FuncIndexInfo fInfo;
- FuncIndexInfo *funcInfo = NULL;
- bool unique;
Form_pg_index index;
- Node *oldPred = NULL;
- List *cnfPred = NULL;
- PredInfo *predInfo;
- Relation heapRelation;
- Relation indexRelation;
- int i;
+ List *cnfPred = NIL;
+ IndexInfo *indexInfo;
+ Node *oldPred;
/*
- * compute index relation id and access method id
+ * Get index's relation id and access method id from pg_class
*/
tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(indexRelationName),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- {
elog(ERROR, "ExtendIndex: index \"%s\" not found",
indexRelationName);
- }
indexId = tuple->t_data->t_oid;
accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam;
/*
- * find pg_index tuple
+ * Extract info from the pg_index tuple for the index
*/
tuple = SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(indexId),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- {
elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
indexRelationName);
- }
-
- /*
- * Extract info from the pg_index tuple
- */
index = (Form_pg_index) GETSTRUCT(tuple);
Assert(index->indexrelid == indexId);
relationId = index->indrelid;
- indproc = index->indproc;
- unique = index->indisunique;
-
- for (i = 0; i < INDEX_MAX_KEYS; i++)
- {
- if (index->indkey[i] == InvalidAttrNumber)
- break;
- }
- numberOfAttributes = i;
+ indexInfo = BuildIndexInfo(tuple);
+ oldPred = indexInfo->ii_Predicate;
- if (VARSIZE(&index->indpred) != 0)
- {
- char *predString;
-
- predString = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(&index->indpred)));
- oldPred = stringToNode(predString);
- pfree(predString);
- }
if (oldPred == NULL)
elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
indexRelationName);
@@ -316,8 +270,11 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
/*
* Convert the extension predicate from parsetree form to plan form,
* so it can be readily evaluated during index creation. Note:
- * "predicate" comes in as a list containing (1) the predicate itself
- * (a where_clause), and (2) a corresponding range table.
+ * "predicate" comes in two parts (1) the predicate expression itself,
+ * and (2) a corresponding range table.
+ *
+ * XXX I think this code is broken --- index_build expects a single
+ * expression not a list --- tgl Jul 00
*/
if (rangetable != NIL)
{
@@ -326,47 +283,20 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
CheckPredicate(cnfPred, rangetable, relationId);
}
- /* make predInfo list to pass to index_build */
- predInfo = (PredInfo *) palloc(sizeof(PredInfo));
- predInfo->pred = (Node *) cnfPred;
- predInfo->oldPred = oldPred;
-
- attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
- sizeof attributeNumberA[0]);
- classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]);
-
-
- for (i = 0; i < numberOfAttributes; i++)
- {
- attributeNumberA[i] = index->indkey[i];
- classObjectId[i] = index->indclass[i];
- }
-
- if (indproc != InvalidOid)
- {
- funcInfo = &fInfo;
- FIsetnArgs(funcInfo, numberOfAttributes);
-
- tuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(indproc),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "ExtendIndex: index procedure %u not found",
- indproc);
-
- namecpy(&(funcInfo->funcName),
- &(((Form_pg_proc) GETSTRUCT(tuple))->proname));
-
- FIsetProcOid(funcInfo, tuple->t_data->t_oid);
- }
+ /* pass new predicate to index_build */
+ indexInfo->ii_Predicate = (Node *) cnfPred;
+ /* Open heap and index rels, and get suitable locks */
heapRelation = heap_open(relationId, ShareLock);
indexRelation = index_open(indexId);
- InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
+ /* Obtain exclusive lock on it, just to be sure */
+ LockRelation(indexRelation, AccessExclusiveLock);
+
+ InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
+ indexRelation, accessMethodId);
- index_build(heapRelation, indexRelation, numberOfAttributes,
- attributeNumberA, funcInfo, predInfo, unique);
+ index_build(heapRelation, indexRelation, indexInfo, oldPred);
/* heap and index rels are closed as a side-effect of index_build */
}
@@ -431,15 +361,15 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
static void
-FuncIndexArgs(IndexElem *funcIndex,
- FuncIndexInfo *funcInfo,
- AttrNumber *attNumP,
- Oid *opOidP,
+FuncIndexArgs(IndexInfo *indexInfo,
+ Oid *classOidP,
+ IndexElem *funcIndex,
Oid relId,
char *accessMethodName,
Oid accessMethodId)
{
- List *rest;
+ Oid argTypes[FUNC_MAX_ARGS];
+ List *arglist;
HeapTuple tuple;
Oid retType;
int argn = 0;
@@ -447,68 +377,77 @@ FuncIndexArgs(IndexElem *funcIndex,
/*
* process the function arguments, which are a list of T_String
* (someday ought to allow more general expressions?)
+ *
+ * Note caller already checked that list is not too long.
*/
- MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid));
+ MemSet(argTypes, 0, sizeof(argTypes));
- foreach(rest, funcIndex->args)
+ foreach(arglist, funcIndex->args)
{
- char *arg = strVal(lfirst(rest));
+ char *arg = strVal(lfirst(arglist));
Form_pg_attribute att;
tuple = SearchSysCacheTuple(ATTNAME,
ObjectIdGetDatum(relId),
- PointerGetDatum(arg), 0, 0);
-
+ PointerGetDatum(arg),
+ 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
att = (Form_pg_attribute) GETSTRUCT(tuple);
- *attNumP++ = att->attnum;
- funcInfo->arglist[argn++] = att->atttypid;
+
+ indexInfo->ii_KeyAttrNumbers[argn] = att->attnum;
+ argTypes[argn] = att->atttypid;
+ argn++;
}
/* ----------------
* Lookup the function procedure to get its OID and result type.
+ *
+ * XXX need to accept binary-compatible functions here, not just
+ * an exact match.
* ----------------
*/
tuple = SearchSysCacheTuple(PROCNAME,
- PointerGetDatum(FIgetname(funcInfo)),
- Int32GetDatum(FIgetnArgs(funcInfo)),
- PointerGetDatum(FIgetArglist(funcInfo)),
+ PointerGetDatum(funcIndex->name),
+ Int32GetDatum(indexInfo->ii_NumKeyAttrs),
+ PointerGetDatum(argTypes),
0);
-
if (!HeapTupleIsValid(tuple))
{
- func_error("DefineIndex", FIgetname(funcInfo),
- FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
+ func_error("DefineIndex", funcIndex->name,
+ indexInfo->ii_NumKeyAttrs, argTypes, NULL);
}
- FIsetProcOid(funcInfo, tuple->t_data->t_oid);
+ indexInfo->ii_FuncOid = tuple->t_data->t_oid;
retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
- /* Process type and opclass, using func return type as default */
+ /* Process opclass, using func return type as default type */
- ProcessAttrTypename(funcIndex, retType, -1);
+ classOidP[0] = GetAttrOpClass(funcIndex, retType,
+ accessMethodName, accessMethodId);
- *opOidP = GetAttrOpClass(funcIndex, retType,
- accessMethodName, accessMethodId);
+ /* Need to do the fmgr function lookup now, too */
+
+ fmgr_info(indexInfo->ii_FuncOid, & indexInfo->ii_FuncInfo);
}
static void
-NormIndexAttrs(List *attList, /* list of IndexElem's */
- AttrNumber *attNumP,
+NormIndexAttrs(IndexInfo *indexInfo,
Oid *classOidP,
+ List *attList, /* list of IndexElem's */
Oid relId,
char *accessMethodName,
Oid accessMethodId)
{
List *rest;
+ int attn = 0;
/*
* process attributeList
*/
foreach(rest, attList)
{
- IndexElem *attribute = lfirst(rest);
+ IndexElem *attribute = (IndexElem *) lfirst(rest);
HeapTuple atttuple;
Form_pg_attribute attform;
@@ -524,36 +463,13 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
attribute->name);
attform = (Form_pg_attribute) GETSTRUCT(atttuple);
- *attNumP++ = attform->attnum;
-
- ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
+ indexInfo->ii_KeyAttrNumbers[attn] = attform->attnum;
- *classOidP++ = GetAttrOpClass(attribute, attform->atttypid,
- accessMethodName, accessMethodId);
+ classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid,
+ accessMethodName, accessMethodId);
heap_freetuple(atttuple);
- }
-}
-
-static void
-ProcessAttrTypename(IndexElem *attribute,
- Oid defType, int32 defTypmod)
-{
- HeapTuple tuple;
-
- /* build a type node so we can set the proper alignment, etc. */
- if (attribute->typename == NULL)
- {
- tuple = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(defType),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined",
- attribute->name);
-
- attribute->typename = makeNode(TypeName);
- attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
- attribute->typename->typmod = defTypmod;
+ attn++;
}
}
@@ -626,7 +542,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
*
* If the opclass was the default for the datatype, assume we can skip
* this check --- that saves a few cycles in the most common case.
- * If pg_opclass is messed up then we're probably screwed anyway...
+ * If pg_opclass is wrong then we're probably screwed anyway...
*/
if (doTypeCheck)
{
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 71682baa8cd..ee0ebeb4bb7 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.162 2000/07/05 16:17:38 wieck Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.163 2000/07/14 22:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
@@ -28,6 +28,7 @@
#include "catalog/index.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
+#include "nodes/execnodes.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
#include "tcop/tcopprot.h"
@@ -71,7 +72,8 @@ static void reap_page(VacPageList vacpagelist, VacPage vacpage);
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
static void get_indices(Relation relation, int *nindices, Relation **Irel);
static void close_indices(int nindices, Relation *Irel);
-static void get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc);
+static IndexInfo **get_index_desc(Relation onerel, int nindices,
+ Relation *Irel);
static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
int (*compar) (const void *, const void *));
static int vac_cmp_blk(const void *left, const void *right);
@@ -948,9 +950,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
newitemid;
HeapTupleData tuple,
newtup;
- TupleDesc tupdesc = NULL;
- Datum *idatum = NULL;
- char *inulls = NULL;
+ TupleDesc tupdesc;
+ IndexInfo **indexInfo = NULL;
+ Datum idatum[INDEX_MAX_KEYS];
+ char inulls[INDEX_MAX_KEYS];
InsertIndexResult iresult;
VacPageListData Nvacpagelist;
VacPage cur_page = NULL,
@@ -958,8 +961,6 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
vacpage,
*curpage;
int cur_item = 0;
- IndDesc *Idesc,
- *idcur;
int last_move_dest_block = -1,
last_vacuum_block,
i = 0;
@@ -980,13 +981,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
myXID = GetCurrentTransactionId();
myCID = GetCurrentCommandId();
+ tupdesc = RelationGetDescr(onerel);
+
if (Irel != (Relation *) NULL) /* preparation for index' inserts */
- {
- get_index_desc(onerel, nindices, Irel, &Idesc);
- tupdesc = RelationGetDescr(onerel);
- idatum = (Datum *) palloc(INDEX_MAX_KEYS * sizeof(*idatum));
- inulls = (char *) palloc(INDEX_MAX_KEYS * sizeof(*inulls));
- }
+ indexInfo = get_index_desc(onerel, nindices, Irel);
Nvacpagelist.num_pages = 0;
num_fraged_pages = fraged_pages->num_pages;
@@ -1456,15 +1454,22 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (Irel != (Relation *) NULL)
{
- for (i = 0, idcur = Idesc; i < nindices; i++, idcur++)
+ /*
+ * XXX using CurrentMemoryContext here means
+ * intra-vacuum memory leak for functional indexes.
+ * Should fix someday.
+ *
+ * XXX This code fails to handle partial indexes!
+ * Probably should change it to use ExecOpenIndices.
+ */
+ for (i = 0; i < nindices; i++)
{
- FormIndexDatum(idcur->natts,
- (AttrNumber *) &(idcur->tform->indkey[0]),
+ FormIndexDatum(indexInfo[i],
&newtup,
tupdesc,
+ CurrentMemoryContext,
idatum,
- inulls,
- idcur->finfoP);
+ inulls);
iresult = index_insert(Irel[i],
idatum,
inulls,
@@ -1575,15 +1580,22 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
/* insert index' tuples if needed */
if (Irel != (Relation *) NULL)
{
- for (i = 0, idcur = Idesc; i < nindices; i++, idcur++)
+ /*
+ * XXX using CurrentMemoryContext here means
+ * intra-vacuum memory leak for functional indexes.
+ * Should fix someday.
+ *
+ * XXX This code fails to handle partial indexes!
+ * Probably should change it to use ExecOpenIndices.
+ */
+ for (i = 0; i < nindices; i++)
{
- FormIndexDatum(idcur->natts,
- (AttrNumber *) &(idcur->tform->indkey[0]),
+ FormIndexDatum(indexInfo[i],
&newtup,
tupdesc,
+ CurrentMemoryContext,
idatum,
- inulls,
- idcur->finfoP);
+ inulls);
iresult = index_insert(Irel[i],
idatum,
inulls,
@@ -1821,10 +1833,8 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
if (Irel != (Relation *) NULL) /* pfree index' allocations */
{
- pfree(Idesc);
- pfree(idatum);
- pfree(inulls);
close_indices(nindices, Irel);
+ pfree(indexInfo);
}
pfree(vacpage);
@@ -2347,46 +2357,30 @@ close_indices(int nindices, Relation *Irel)
}
-static void
-get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc)
+/*
+ * Obtain IndexInfo data for each index on the rel
+ */
+static IndexInfo **
+get_index_desc(Relation onerel, int nindices, Relation *Irel)
{
- IndDesc *idcur;
- HeapTuple cachetuple;
- AttrNumber *attnumP;
- int natts;
+ IndexInfo **indexInfo;
int i;
+ HeapTuple cachetuple;
- *Idesc = (IndDesc *) palloc(nindices * sizeof(IndDesc));
+ indexInfo = (IndexInfo **) palloc(nindices * sizeof(IndexInfo *));
- for (i = 0, idcur = *Idesc; i < nindices; i++, idcur++)
+ for (i = 0; i < nindices; i++)
{
- cachetuple = SearchSysCacheTupleCopy(INDEXRELID,
+ cachetuple = SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(RelationGetRelid(Irel[i])),
- 0, 0, 0);
- Assert(cachetuple);
-
- /*
- * we never free the copy we make, because Idesc needs it for
- * later
- */
- idcur->tform = (Form_pg_index) GETSTRUCT(cachetuple);
- for (attnumP = &(idcur->tform->indkey[0]), natts = 0;
- natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber;
- attnumP++, natts++);
- if (idcur->tform->indproc != InvalidOid)
- {
- idcur->finfoP = &(idcur->finfo);
- FIgetnArgs(idcur->finfoP) = natts;
- natts = 1;
- FIgetProcOid(idcur->finfoP) = idcur->tform->indproc;
- *(FIgetname(idcur->finfoP)) = '\0';
- }
- else
- idcur->finfoP = (FuncIndexInfo *) NULL;
-
- idcur->natts = natts;
+ 0, 0, 0);
+ if (!HeapTupleIsValid(cachetuple))
+ elog(ERROR, "get_index_desc: index %u not found",
+ RelationGetRelid(Irel[i]));
+ indexInfo[i] = BuildIndexInfo(cachetuple);
}
+ return indexInfo;
}