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 | |
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')
-rw-r--r-- | src/backend/access/gist/gist.c | 154 | ||||
-rw-r--r-- | src/backend/access/hash/hash.c | 90 | ||||
-rw-r--r-- | src/backend/access/index/indexam.c | 55 | ||||
-rw-r--r-- | src/backend/access/index/istrat.c | 15 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 105 | ||||
-rw-r--r-- | src/backend/access/rtree/rtree.c | 129 |
6 files changed, 187 insertions, 361 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(); } diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 354d4985723..cb740bbde9e 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.41 2000/07/12 02:36:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.42 2000/07/14 22:17:28 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -41,42 +41,32 @@ hashbuild(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 hscan; HeapTuple htup; IndexTuple itup; TupleDesc htupdesc, itupdesc; - Datum *attdata; - bool *nulls; - InsertIndexResult res; + Datum attdata[INDEX_MAX_KEYS]; + char nulls[INDEX_MAX_KEYS]; int nhtups, nitups; - int i; HashItem hitem; - + Node *pred = indexInfo->ii_Predicate; #ifndef OMIT_PARTIAL_INDEX - ExprContext *econtext; TupleTable tupleTable; TupleTableSlot *slot; - #endif - Node *pred, - *oldPred; + ExprContext *econtext; + InsertIndexResult res = NULL; - /* note that this is a new btree */ + /* note that this is a new hash */ BuildingHash = true; - pred = predInfo->pred; - oldPred = predInfo->oldPred; - /* initialize the hash index metadata page (if this is a new index) */ if (oldPred == NULL) _hash_metapinit(index); @@ -85,17 +75,15 @@ hashbuild(PG_FUNCTION_ARGS) htupdesc = RelationGetDescr(heap); itupdesc = RelationGetDescr(index); - /* get space for data items that'll appear in the index tuple */ - attdata = (Datum *) palloc(natts * sizeof(Datum)); - nulls = (bool *) palloc(natts * sizeof(bool)); - /* * 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) @@ -103,14 +91,15 @@ hashbuild(PG_FUNCTION_ARGS) tupleTable = ExecCreateTupleTable(1); slot = ExecAllocTableSlot(tupleTable); ExecSetSlotDescriptor(slot, htupdesc); - econtext = MakeExprContext(slot, TransactionCommandContext); } else { tupleTable = NULL; slot = NULL; - econtext = NULL; } + econtext = MakeExprContext(slot, TransactionCommandContext); +#else + econtext = MakeExprContext(NULL, TransactionCommandContext); #endif /* OMIT_PARTIAL_INDEX */ /* build the index */ @@ -121,6 +110,8 @@ hashbuild(PG_FUNCTION_ARGS) while (HeapTupleIsValid(htup = heap_getnext(hscan, 0))) { + MemoryContextReset(econtext->ecxt_per_tuple_memory); + nhtups++; #ifndef OMIT_PARTIAL_INDEX @@ -130,7 +121,6 @@ hashbuild(PG_FUNCTION_ARGS) */ if (oldPred != NULL) { - /* SetSlotContents(slot, htup); */ slot->val = htup; if (ExecQual((List *) oldPred, econtext, false)) { @@ -145,7 +135,6 @@ hashbuild(PG_FUNCTION_ARGS) */ if (pred != NULL) { - /* SetSlotContents(slot, htup); */ slot->val = htup; if (!ExecQual((List *) pred, econtext, false)) continue; @@ -158,33 +147,12 @@ hashbuild(PG_FUNCTION_ARGS) * 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 = i - 1 */ - attoff = AttrNumberGetAttrOffset(i); - - /* - * below, attdata[attoff] set to equal some datum & attnull is - * changed to indicate whether or not the attribute is null - * for this tuple - */ - attdata[attoff] = GetIndexValue(htup, - htupdesc, - attoff, - attnum, - finfo, - &attnull); - nulls[attoff] = (attnull ? 'n' : ' '); - } + FormIndexDatum(indexInfo, + htup, + htupdesc, + econtext->ecxt_per_tuple_memory, + attdata, + nulls); /* form an index tuple and point it at the heap tuple */ itup = index_formtuple(itupdesc, attdata, nulls); @@ -208,7 +176,9 @@ hashbuild(PG_FUNCTION_ARGS) itup->t_tid = htup->t_self; hitem = _hash_formitem(itup); + res = _hash_doinsert(index, hitem); + pfree(hitem); pfree(itup); pfree(res); @@ -221,9 +191,9 @@ hashbuild(PG_FUNCTION_ARGS) 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 @@ -254,10 +224,6 @@ hashbuild(PG_FUNCTION_ARGS) } } - /* be tidy */ - pfree(nulls); - pfree(attdata); - /* all done */ BuildingHash = false; diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 2d1504238de..dc18b0d3b77 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.45 2000/06/13 07:34:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.46 2000/07/14 22:17:30 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relationId @@ -424,56 +424,3 @@ index_getprocid(Relation irel, return loc[(natts * (procnum - 1)) + (attnum - 1)]; } - -Datum -GetIndexValue(HeapTuple tuple, - TupleDesc hTupDesc, - int attOff, - AttrNumber *attrNums, - FuncIndexInfo *fInfo, - bool *attNull) -{ - Datum returnVal; - - if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidOid) - { - FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - int i; - bool anynull = false; - - /* - * XXX ought to store lookup info in FuncIndexInfo so it need not - * be repeated on each call? - */ - fmgr_info(FIgetProcOid(fInfo), &flinfo); - - MemSet(&fcinfo, 0, sizeof(fcinfo)); - fcinfo.flinfo = &flinfo; - fcinfo.nargs = FIgetnArgs(fInfo); - - for (i = 0; i < FIgetnArgs(fInfo); i++) - { - fcinfo.arg[i] = heap_getattr(tuple, - attrNums[i], - hTupDesc, - &fcinfo.argnull[i]); - anynull |= fcinfo.argnull[i]; - } - if (flinfo.fn_strict && anynull) - { - /* force a null result for strict function */ - returnVal = (Datum) 0; - *attNull = true; - } - else - { - returnVal = FunctionCallInvoke(&fcinfo); - *attNull = fcinfo.isnull; - } - } - else - returnVal = heap_getattr(tuple, attrNums[attOff], hTupDesc, attNull); - - return returnVal; -} diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c index fc7ac6dcb14..d6a966bcd44 100644 --- a/src/backend/access/index/istrat.c +++ b/src/backend/access/index/istrat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.45 2000/06/08 22:36:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.46 2000/07/14 22:17:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -533,6 +533,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation, void IndexSupportInitialize(IndexStrategy indexStrategy, RegProcedure *indexSupport, + bool *isUnique, Oid indexObjectId, Oid accessMethodObjectId, StrategyNumber maxStrategyNumber, @@ -544,6 +545,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy, ScanKeyData entry[2]; Relation operatorRelation; HeapTuple tuple; + Form_pg_index iform; StrategyMap map; AttrNumber attributeNumber; int attributeIndex; @@ -568,7 +570,12 @@ IndexSupportInitialize(IndexStrategy indexStrategy, } if (!HeapTupleIsValid(tuple)) - elog(ERROR, "IndexSupportInitialize: corrupted catalogs"); + elog(ERROR, "IndexSupportInitialize: no pg_index entry for index %u", + indexObjectId); + + iform = (Form_pg_index) GETSTRUCT(tuple); + + *isUnique = iform->indisunique; maxStrategyNumber = AMStrategies(maxStrategyNumber); @@ -578,10 +585,6 @@ IndexSupportInitialize(IndexStrategy indexStrategy, */ for (attributeIndex = 0; attributeIndex < maxAttributeNumber; attributeIndex++) { - Form_pg_index iform; - - iform = (Form_pg_index) GETSTRUCT(tuple); - if (!OidIsValid(iform->indkey[attributeIndex])) { if (attributeIndex == InvalidAttrNumber) diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 3d8ea1a70a8..b174d303176 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.60 2000/07/12 02:36:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.61 2000/07/14 22:17:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,44 +45,34 @@ btbuild(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); - bool unique = PG_GETARG_BOOL(6); + IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); + Node *oldPred = (Node *) PG_GETARG_POINTER(3); #ifdef NOT_USED - IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(7); + IndexStrategy istrat = (IndexStrategy) PG_GETARG_POINTER(4); #endif HeapScanDesc hscan; HeapTuple htup; IndexTuple itup; TupleDesc htupdesc, itupdesc; - Datum *attdata; - bool *nulls; - InsertIndexResult res = 0; + Datum attdata[INDEX_MAX_KEYS]; + char nulls[INDEX_MAX_KEYS]; int nhtups, nitups; - int i; - BTItem btitem; - + Node *pred = indexInfo->ii_Predicate; #ifndef OMIT_PARTIAL_INDEX - ExprContext *econtext = (ExprContext *) NULL; - TupleTable tupleTable = (TupleTable) NULL; - TupleTableSlot *slot = (TupleTableSlot *) NULL; - + TupleTable tupleTable; + TupleTableSlot *slot; #endif - Node *pred, - *oldPred; + ExprContext *econtext; + InsertIndexResult res = NULL; BTSpool *spool = NULL; + BTItem btitem; bool usefast; /* note that this is a new btree */ BuildingBtree = true; - pred = predInfo->pred; - oldPred = predInfo->oldPred; - /* * bootstrap processing does something strange, so don't use * sort/build for initial catalog indices. at some point i need to @@ -104,17 +94,15 @@ btbuild(PG_FUNCTION_ARGS) htupdesc = RelationGetDescr(heap); itupdesc = RelationGetDescr(index); - /* get space for data items that'll appear in the index tuple */ - attdata = (Datum *) palloc(natts * sizeof(Datum)); - nulls = (bool *) palloc(natts * sizeof(bool)); - /* * 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) @@ -122,7 +110,6 @@ btbuild(PG_FUNCTION_ARGS) tupleTable = ExecCreateTupleTable(1); slot = ExecAllocTableSlot(tupleTable); ExecSetSlotDescriptor(slot, htupdesc); - econtext = MakeExprContext(slot, TransactionCommandContext); /* * we never want to use sort/build if we are extending an existing @@ -133,22 +120,29 @@ btbuild(PG_FUNCTION_ARGS) */ usefast = false; } + else + { + tupleTable = NULL; + slot = NULL; + } + econtext = MakeExprContext(slot, TransactionCommandContext); +#else + econtext = MakeExprContext(NULL, TransactionCommandContext); #endif /* OMIT_PARTIAL_INDEX */ - /* start a heap scan */ /* build the index */ nhtups = nitups = 0; if (usefast) - { - spool = _bt_spoolinit(index, unique); - res = (InsertIndexResult) NULL; - } + spool = _bt_spoolinit(index, indexInfo->ii_Unique); + /* start a heap scan */ hscan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL); while (HeapTupleIsValid(htup = heap_getnext(hscan, 0))) { + MemoryContextReset(econtext->ecxt_per_tuple_memory); + nhtups++; #ifndef OMIT_PARTIAL_INDEX @@ -158,7 +152,6 @@ btbuild(PG_FUNCTION_ARGS) */ if (oldPred != NULL) { - /* SetSlotContents(slot, htup); */ slot->val = htup; if (ExecQual((List *) oldPred, econtext, false)) { @@ -173,7 +166,6 @@ btbuild(PG_FUNCTION_ARGS) */ if (pred != NULL) { - /* SetSlotContents(slot, htup); */ slot->val = htup; if (!ExecQual((List *) pred, econtext, false)) continue; @@ -186,27 +178,12 @@ btbuild(PG_FUNCTION_ARGS) * 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); - attdata[attoff] = GetIndexValue(htup, - htupdesc, - attoff, - attnum, - finfo, - &attnull); - nulls[attoff] = (attnull ? 'n' : ' '); - } + FormIndexDatum(indexInfo, + htup, + htupdesc, + econtext->ecxt_per_tuple_memory, + attdata, + nulls); /* form an index tuple and point it at the heap tuple */ itup = index_formtuple(itupdesc, attdata, nulls); @@ -246,7 +223,7 @@ btbuild(PG_FUNCTION_ARGS) if (usefast) _bt_spool(btitem, spool); else - res = _bt_doinsert(index, btitem, unique, heap); + res = _bt_doinsert(index, btitem, indexInfo->ii_Unique, heap); pfree(btitem); pfree(itup); @@ -261,9 +238,9 @@ btbuild(PG_FUNCTION_ARGS) if (pred != NULL || oldPred != NULL) { ExecDropTupleTable(tupleTable, true); - FreeExprContext(econtext); } #endif /* OMIT_PARTIAL_INDEX */ + FreeExprContext(econtext); /* * if we are doing bottom-up btree build, finish the build by (1) @@ -305,10 +282,6 @@ btbuild(PG_FUNCTION_ARGS) heap_close(heap, NoLock); index_close(index); - /* - * UpdateStats(hrelid, nhtups, true); UpdateStats(irelid, nitups, - * false); - */ UpdateStats(hrelid, nhtups, inplace); UpdateStats(irelid, nitups, inplace); if (oldPred != NULL) @@ -320,9 +293,6 @@ btbuild(PG_FUNCTION_ARGS) } } - pfree(nulls); - pfree(attdata); - /* all done */ BuildingBtree = false; @@ -361,8 +331,7 @@ btinsert(PG_FUNCTION_ARGS) btitem = _bt_formitem(itup); - res = _bt_doinsert(rel, btitem, - IndexIsUnique(RelationGetRelid(rel)), heapRel); + res = _bt_doinsert(rel, btitem, rel->rd_uniqueindex, heapRel); pfree(btitem); pfree(itup); diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c index badff1ee21b..583baa534a3 100644 --- a/src/backend/access/rtree/rtree.c +++ b/src/backend/access/rtree/rtree.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.51 2000/07/12 02:36:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.52 2000/07/14 22:17:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -64,49 +64,37 @@ rtbuild(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; - Buffer buffer = InvalidBuffer; - 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; + Buffer buffer = InvalidBuffer; RTSTATE rtState; initRtstate(&rtState, 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) */ @@ -117,44 +105,48 @@ rtbuild(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 */ /* count the tuples as we insert them */ - nh = ni = 0; + nhtups = nitups = 0; - scan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL); + /* start a heap scan */ + hscan = heap_beginscan(heap, 0, SnapshotNow, 0, (ScanKey) NULL); - while (HeapTupleIsValid(htup = heap_getnext(scan, 0))) + while (HeapTupleIsValid(htup = heap_getnext(hscan, 0))) { - nh++; + MemoryContextReset(econtext->ecxt_per_tuple_memory); + + nhtups++; #ifndef OMIT_PARTIAL_INDEX /* @@ -163,11 +155,10 @@ rtbuild(PG_FUNCTION_ARGS) */ if (oldPred != NULL) { - /* SetSlotContents(slot, htup); */ slot->val = htup; if (ExecQual((List *) oldPred, econtext, false)) { - ni++; + nitups++; continue; } } @@ -178,47 +169,27 @@ rtbuild(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); /* 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; /* @@ -235,15 +206,15 @@ rtbuild(PG_FUNCTION_ARGS) } /* okay, all heap tuples are indexed */ - heap_endscan(scan); + heap_endscan(hscan); #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 @@ -264,20 +235,16 @@ rtbuild(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(); } |