diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-14 22:18:02 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-14 22:18:02 +0000 |
commit | 6bfe64032efd043f80a495a495331dcfc2d9f05c (patch) | |
tree | d0cc092d38bdea690a79e4aebfa4629e1db54e96 /src/backend/access/gist/gist.c | |
parent | a30bc7c75a54910a78d1939bd32f5d91164ba8a4 (diff) | |
download | postgresql-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.c | 154 |
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(); } |