aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gist.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-07-14 22:18:02 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-07-14 22:18:02 +0000
commit6bfe64032efd043f80a495a495331dcfc2d9f05c (patch)
treed0cc092d38bdea690a79e4aebfa4629e1db54e96 /src/backend/access/gist/gist.c
parenta30bc7c75a54910a78d1939bd32f5d91164ba8a4 (diff)
downloadpostgresql-6bfe64032efd043f80a495a495331dcfc2d9f05c.tar.gz
postgresql-6bfe64032efd043f80a495a495331dcfc2d9f05c.zip
Cleanup of code for creating index entries. Functional indexes with
pass-by-ref data types --- eg, an index on lower(textfield) --- no longer leak memory during index creation or update. Clean up a lot of redundant code ... did you know that copy, vacuum, truncate, reindex, extend index, and bootstrap each basically duplicated the main executor's logic for extracting information about an index and preparing index entries? Functional indexes should be a little faster now too, due to removal of repeated function lookups. CREATE INDEX 'opt_type' clause is deimplemented by these changes, but I haven't removed it from the parser yet (need to merge with Thomas' latest change set first).
Diffstat (limited to 'src/backend/access/gist/gist.c')
-rw-r--r--src/backend/access/gist/gist.c154
1 files changed, 64 insertions, 90 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 28c547ffe69..640c1898860 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.61 2000/07/12 02:36:46 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.62 2000/07/14 22:17:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,53 +65,42 @@ gistbuild(PG_FUNCTION_ARGS)
{
Relation heap = (Relation) PG_GETARG_POINTER(0);
Relation index = (Relation) PG_GETARG_POINTER(1);
- int32 natts = PG_GETARG_INT32(2);
- AttrNumber *attnum = (AttrNumber *) PG_GETARG_POINTER(3);
- FuncIndexInfo *finfo = (FuncIndexInfo *) PG_GETARG_POINTER(4);
- PredInfo *predInfo = (PredInfo *) PG_GETARG_POINTER(5);
+ IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2);
+ Node *oldPred = (Node *) PG_GETARG_POINTER(3);
#ifdef NOT_USED
- bool unique = PG_GETARG_BOOL(6);
- IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(7);
+ IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4);
#endif
- HeapScanDesc scan;
- AttrNumber i;
+ HeapScanDesc hscan;
HeapTuple htup;
IndexTuple itup;
- TupleDesc hd,
- id;
- InsertIndexResult res;
- Datum *d;
- bool *nulls;
- int nb,
- nh,
- ni;
+ TupleDesc htupdesc,
+ itupdesc;
+ Datum attdata[INDEX_MAX_KEYS];
+ char nulls[INDEX_MAX_KEYS];
+ int nhtups,
+ nitups;
+ Node *pred = indexInfo->ii_Predicate;
#ifndef OMIT_PARTIAL_INDEX
- ExprContext *econtext;
TupleTable tupleTable;
TupleTableSlot *slot;
#endif
- Node *pred,
- *oldPred;
+ ExprContext *econtext;
+ InsertIndexResult res = NULL;
GISTSTATE giststate;
GISTENTRY tmpcentry;
Buffer buffer = InvalidBuffer;
bool *compvec;
+ int i;
/* no locking is needed */
- CommandCounterIncrement(); /* so we can see the new pg_index tuple */
-
initGISTstate(&giststate, index);
- pred = predInfo->pred;
- oldPred = predInfo->oldPred;
-
/*
* We expect to be called exactly once for any index relation. If
* that's not the case, big trouble's what we have.
*/
-
- if (oldPred == NULL && (nb = RelationGetNumberOfBlocks(index)) != 0)
+ if (oldPred == NULL && RelationGetNumberOfBlocks(index) != 0)
elog(ERROR, "%s already contains data", RelationGetRelationName(index));
/* initialize the root page (if this is a new index) */
@@ -122,43 +111,50 @@ gistbuild(PG_FUNCTION_ARGS)
WriteBuffer(buffer);
}
- /* init the tuple descriptors and get set for a heap scan */
- hd = RelationGetDescr(heap);
- id = RelationGetDescr(index);
- d = (Datum *) palloc(natts * sizeof(*d));
- nulls = (bool *) palloc(natts * sizeof(*nulls));
+ /* get tuple descriptors for heap and index relations */
+ htupdesc = RelationGetDescr(heap);
+ itupdesc = RelationGetDescr(index);
/*
* 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
+ * TupleTable and ExprContext objects for this purpose. --Nels, Feb 92
+ *
+ * We construct the ExprContext anyway since we need a per-tuple
+ * temporary memory context for function evaluation -- tgl July 00
*/
#ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL)
{
tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable);
- ExecSetSlotDescriptor(slot, hd);
- econtext = MakeExprContext(slot, TransactionCommandContext);
+ ExecSetSlotDescriptor(slot, htupdesc);
}
else
{
tupleTable = NULL;
slot = NULL;
- econtext = NULL;
}
+ econtext = MakeExprContext(slot, TransactionCommandContext);
+#else
+ econtext = MakeExprContext(NULL, TransactionCommandContext);
#endif /* OMIT_PARTIAL_INDEX */
- /* int the tuples as we insert them */
- nh = ni = 0;
- scan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL);
+ /* build the index */
+ nhtups = nitups = 0;
+
+ compvec = (bool *) palloc(sizeof(bool) * indexInfo->ii_NumIndexAttrs);
- while (HeapTupleIsValid(htup = heap_getnext(scan, 0)))
+ /* start a heap scan */
+ hscan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL);
+
+ while (HeapTupleIsValid(htup = heap_getnext(hscan, 0)))
{
- nh++;
+ MemoryContextReset(econtext->ecxt_per_tuple_memory);
+
+ nhtups++;
#ifndef OMIT_PARTIAL_INDEX
/*
@@ -167,11 +163,10 @@ gistbuild(PG_FUNCTION_ARGS)
*/
if (oldPred != NULL)
{
- /* SetSlotContents(slot, htup); */
slot->val = htup;
if (ExecQual((List *) oldPred, econtext, false))
{
- ni++;
+ nitups++;
continue;
}
}
@@ -182,61 +177,41 @@ gistbuild(PG_FUNCTION_ARGS)
*/
if (pred != NULL)
{
- /* SetSlotContents(slot, htup); */
slot->val = htup;
if (!ExecQual((List *) pred, econtext, false))
continue;
}
#endif /* OMIT_PARTIAL_INDEX */
- ni++;
+ nitups++;
/*
* For the current heap tuple, extract all the attributes we use
* in this index, and note which are null.
*/
-
- for (i = 1; i <= natts; i++)
- {
- int attoff;
- bool attnull;
-
- /*
- * Offsets are from the start of the tuple, and are
- * zero-based; indices are one-based. The next call returns i
- * - 1. That's data hiding for you.
- */
-
- attoff = AttrNumberGetAttrOffset(i);
-
- /*
- * d[attoff] = HeapTupleGetAttributeValue(htup, buffer,
- */
- d[attoff] = GetIndexValue(htup,
- hd,
- attoff,
- attnum,
- finfo,
- &attnull);
- nulls[attoff] = (attnull ? 'n' : ' ');
- }
+ FormIndexDatum(indexInfo,
+ htup,
+ htupdesc,
+ econtext->ecxt_per_tuple_memory,
+ attdata,
+ nulls);
/* immediately compress keys to normalize */
- compvec = (bool *) palloc(sizeof(bool) * natts);
- for (i = 0; i < natts; i++)
+ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
{
- gistcentryinit(&giststate, &tmpcentry, (char *) d[i],
+ gistcentryinit(&giststate, &tmpcentry, (char *) attdata[i],
(Relation) NULL, (Page) NULL, (OffsetNumber) 0,
-1 /* size is currently bogus */ , TRUE);
- if (d[i] != (Datum) tmpcentry.pred && !(giststate.keytypbyval))
+ if (attdata[i] != (Datum) tmpcentry.pred &&
+ !(giststate.keytypbyval))
compvec[i] = TRUE;
else
compvec[i] = FALSE;
- d[i] = (Datum) tmpcentry.pred;
+ attdata[i] = (Datum) tmpcentry.pred;
}
/* form an index tuple and point it at the heap tuple */
- itup = index_formtuple(id, &d[0], nulls);
+ itup = index_formtuple(itupdesc, attdata, nulls);
itup->t_tid = htup->t_self;
/*
@@ -248,24 +223,27 @@ gistbuild(PG_FUNCTION_ARGS)
*/
res = gistdoinsert(index, itup, &giststate);
- for (i = 0; i < natts; i++)
- if (compvec[i] == TRUE)
- pfree((char *) d[i]);
+
+ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ if (compvec[i])
+ pfree(DatumGetPointer(attdata[i]));
+
pfree(itup);
pfree(res);
- pfree(compvec);
}
/* okay, all heap tuples are indexed */
- heap_endscan(scan);
+ heap_endscan(hscan);
+
+ pfree(compvec);
#ifndef OMIT_PARTIAL_INDEX
if (pred != NULL || oldPred != NULL)
{
ExecDropTupleTable(tupleTable, true);
- FreeExprContext(econtext);
}
#endif /* OMIT_PARTIAL_INDEX */
+ FreeExprContext(econtext);
/*
* Since we just counted the tuples in the heap, we update its stats
@@ -286,20 +264,16 @@ gistbuild(PG_FUNCTION_ARGS)
heap_close(heap, NoLock);
index_close(index);
- UpdateStats(hrelid, nh, inplace);
- UpdateStats(irelid, ni, inplace);
+ UpdateStats(hrelid, nhtups, inplace);
+ UpdateStats(irelid, nitups, inplace);
if (oldPred != NULL && !inplace)
{
- if (ni == nh)
+ if (nitups == nhtups)
pred = NULL;
UpdateIndexPredicate(irelid, oldPred, pred);
}
}
- /* be tidy */
- pfree(nulls);
- pfree(d);
-
PG_RETURN_VOID();
}