diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 28c547ffe69fc8376bd95835f815e2d8480ddbb4..640c189886021154fbfc37b7a7a04910792c0642 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 354d4985723cafa06c48355dd47fffbcf041330b..cb740bbde9ed179379af480d337655cbd7302545 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 2d1504238deb9cd4375cc40f6187a7c287c5df40..dc18b0d3b776c9f8004f2c5f96618428307cbc60 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 fc7ac6dcb142b9dc771448593a0098a552cb119c..d6a966bcd44a700c19f0ac8c6c45ef56787d7fb8 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 3d8ea1a70a8e8e04eb93d2e324b63f7506618ce7..b174d303176e95f04db9429992b673b42d7125f8 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 badff1ee21bec6f5b172755398a4429f598e61cb..583baa534a369e2c8a6957fbf4f22a4ff03ad63a 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(); } diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 4c13aafc0eb075a05602aface14d607280182c1a..cf3cd1b280bd2be208766f5361d53b456b54ef22 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.31 2000/07/04 06:11:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.32 2000/07/14 22:17:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,6 @@ #include "access/attnum.h" -#include "access/funcindex.h" #include "access/htup.h" #include "access/itup.h" #include "access/skey.h" diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l index 125ea516f17b5f0ead02cd2c1e706c70c93c2034..ed68c92ac289fc40e3e17e49ec9be45cf0608b31 100644 --- a/src/backend/bootstrap/bootscanner.l +++ b/src/backend/bootstrap/bootscanner.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.17 2000/01/26 05:56:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.18 2000/07/14 22:17:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,6 @@ #include "postgres.h" #include "access/attnum.h" -#include "access/funcindex.h" #include "access/htup.h" #include "access/itup.h" #include "access/skey.h" diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 1c52d098a1aaa559cdf68ab6e30df2c20e2caac3..c3cf93717241ec962fb10b37c19dcc9f9319d48a 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.90 2000/07/03 23:09:23 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.91 2000/07/14 22:17:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -160,20 +160,12 @@ typedef struct _IndexList { char *il_heap; char *il_ind; - int il_natts; - AttrNumber *il_attnos; - FuncIndexInfo *il_finfo; - PredInfo *il_predInfo; - bool il_unique; + IndexInfo *il_info; struct _IndexList *il_next; } IndexList; static IndexList *ILHead = (IndexList *) NULL; -typedef void (*sig_func) (); - - - /* ---------------------------------------------------------------- * misc functions @@ -334,9 +326,9 @@ BootstrapMain(int argc, char *argv[]) if (!IsUnderPostmaster) { - pqsignal(SIGINT, (sig_func) die); - pqsignal(SIGHUP, (sig_func) die); - pqsignal(SIGTERM, (sig_func) die); + pqsignal(SIGINT, (pqsigfunc) die); + pqsignal(SIGHUP, (pqsigfunc) die); + pqsignal(SIGTERM, (pqsigfunc) die); } /* @@ -1080,14 +1072,9 @@ AddStr(char *str, int strlength, int mderef) void index_register(char *heap, char *ind, - int natts, - AttrNumber *attnos, - FuncIndexInfo *finfo, - PredInfo *predInfo, - bool unique) + IndexInfo *indexInfo) { IndexList *newind; - int len; MemoryContext oldcxt; /* @@ -1108,37 +1095,13 @@ index_register(char *heap, newind = (IndexList *) palloc(sizeof(IndexList)); newind->il_heap = pstrdup(heap); newind->il_ind = pstrdup(ind); - newind->il_natts = natts; - - if (PointerIsValid(finfo)) - len = FIgetnArgs(finfo) * sizeof(AttrNumber); - else - len = natts * sizeof(AttrNumber); - - newind->il_attnos = (AttrNumber *) palloc(len); - memcpy(newind->il_attnos, attnos, len); - - if (PointerIsValid(finfo)) - { - newind->il_finfo = (FuncIndexInfo *) palloc(sizeof(FuncIndexInfo)); - memcpy(newind->il_finfo, finfo, sizeof(FuncIndexInfo)); - } - else - newind->il_finfo = (FuncIndexInfo *) NULL; + newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo)); - if (predInfo != NULL) - { - newind->il_predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - newind->il_predInfo->pred = predInfo->pred; - newind->il_predInfo->oldPred = predInfo->oldPred; - } - else - newind->il_predInfo = NULL; - - newind->il_unique = unique; + memcpy(newind->il_info, indexInfo, sizeof(IndexInfo)); + /* predicate will likely be null anyway, but may as well copy it */ + newind->il_info->ii_Predicate = copyObject(indexInfo->ii_Predicate); newind->il_next = ILHead; - ILHead = newind; MemoryContextSwitchTo(oldcxt); @@ -1147,18 +1110,16 @@ index_register(char *heap, void build_indices() { - Relation heap; - Relation ind; - for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next) { + Relation heap; + Relation ind; + heap = heap_openr(ILHead->il_heap, NoLock); Assert(heap); ind = index_openr(ILHead->il_ind); Assert(ind); - index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos, - ILHead->il_finfo, ILHead->il_predInfo, - ILHead->il_unique); + index_build(heap, ind, ILHead->il_info, NULL); /* * In normal processing mode, index_build would close the heap and diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 08b5e64c53def257e5b035f1adfdf8e2d9b3391f..b5334de15ed33aa5f51ccd21c8d6778ba4ccb095 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.139 2000/07/05 23:11:06 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.140 2000/07/14 22:17:40 tgl Exp $ * * * INTERFACE ROUTINES @@ -1073,91 +1073,37 @@ RelationTruncateIndexes(Relation heapRelation) ScanKeyData entry; HeapScanDesc scan; HeapTuple indexTuple, - procTuple, classTuple; - Form_pg_index index; + IndexInfo *indexInfo; Oid heapId, indexId, - procId, accessMethodId; - Node *oldPred = NULL; - PredInfo *predInfo; - List *cnfPred = NULL; - AttrNumber *attributeNumberA; - FuncIndexInfo fInfo, - *funcInfo = NULL; - bool unique; - int i, - numberOfAttributes; - char *predString; heapId = RelationGetRelid(heapRelation); /* Scan pg_index to find indexes on heapRelation */ - indexRelation = heap_openr(IndexRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ, ObjectIdGetDatum(heapId)); scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry); while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { - /* - * For each index, fetch index attributes so we can apply - * index_build + * For each index, fetch info needed for index_build */ - index = (Form_pg_index) GETSTRUCT(indexTuple); - indexId = index->indexrelid; - procId = index->indproc; - unique = index->indisunique; - - for (i = 0; i < INDEX_MAX_KEYS; i++) - { - if (index->indkey[i] == InvalidAttrNumber) - break; - } - numberOfAttributes = i; - - /* If a valid where predicate, compute predicate Node */ - if (VARSIZE(&index->indpred) != 0) - { - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&index->indpred))); - oldPred = stringToNode(predString); - pfree(predString); - } - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = (Node *) cnfPred; - predInfo->oldPred = oldPred; - - /* Assign Index keys to attributes array */ - attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * - sizeof(AttrNumber)); - for (i = 0; i < numberOfAttributes; i++) - attributeNumberA[i] = index->indkey[i]; - - /* If this is a procedural index, initialize our FuncIndexInfo */ - if (procId != InvalidOid) - { - funcInfo = &fInfo; - FIsetnArgs(funcInfo, numberOfAttributes); - procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId), - 0, 0, 0); - if (!HeapTupleIsValid(procTuple)) - elog(ERROR, "RelationTruncateIndexes: index procedure not found"); - namecpy(&(funcInfo->funcName), - &(((Form_pg_proc) GETSTRUCT(procTuple))->proname)); - FIsetProcOid(funcInfo, procTuple->t_data->t_oid); - } + indexId = ((Form_pg_index) GETSTRUCT(indexTuple))->indexrelid; + indexInfo = BuildIndexInfo(indexTuple); - /* Fetch the classTuple associated with this index */ - classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), + /* Fetch the pg_class tuple associated with this index */ + classTuple = SearchSysCacheTupleCopy(RELOID, + ObjectIdGetDatum(indexId), 0, 0, 0); if (!HeapTupleIsValid(classTuple)) - elog(ERROR, "RelationTruncateIndexes: index access method not found"); + elog(ERROR, "RelationTruncateIndexes: index %u not found in pg_class", + indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; - /* Open our index relation */ + /* Open the index relation */ currentIndex = index_open(indexId); if (currentIndex == NULL) elog(ERROR, "RelationTruncateIndexes: can't open index relation"); @@ -1176,9 +1122,9 @@ RelationTruncateIndexes(Relation heapRelation) currentIndex->rd_nblocks = 0; /* Initialize the index and rebuild */ - InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId); - index_build(heapRelation, currentIndex, numberOfAttributes, - attributeNumberA, funcInfo, predInfo, unique); + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, + currentIndex, accessMethodId); + index_build(heapRelation, currentIndex, indexInfo, NULL); /* * index_build will close both the heap and index relations (but diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 41d747b0dbfe534d8f0bc0bea5846391c2d1718a..2cbcb91ac0685d8a1e6d03509cc3430a8a915ba5 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.125 2000/07/12 02:36:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.126 2000/07/14 22:17:41 tgl Exp $ * * * INTERFACE ROUTINES * index_create() - Create a cataloged index relation * index_drop() - Removes index relation from catalogs - * + * BuildIndexInfo() - Prepare to insert index tuples + * FormIndexDatum() - Construct datum vector for one index tuple * *------------------------------------------------------------------------- */ @@ -58,28 +59,29 @@ /* non-export function prototypes */ static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp); -static TupleDesc BuildFuncTupleDesc(FuncIndexInfo *funcInfo); +static TupleDesc BuildFuncTupleDesc(Oid funcOid); static TupleDesc ConstructTupleDescriptor(Oid heapoid, Relation heapRelation, - List *attributeList, int numatts, AttrNumber *attNums); - + int numatts, AttrNumber *attNums); static void ConstructIndexReldesc(Relation indexRelation, Oid amoid); static Oid UpdateRelationRelation(Relation indexRelation, char *temp_relname); 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, bool primary); + IndexInfo *indexInfo, + Oid *classOids, + bool islossy, bool primary); static void DefaultBuild(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, AttrNumber *attributeNumber, - FuncIndexInfoPtr funcInfo, PredInfo *predInfo, - bool unique, IndexStrategy indexStrategy); + IndexInfo *indexInfo, Node *oldPred, + IndexStrategy indexStrategy); static Oid IndexGetRelation(Oid indexId); static bool activate_index(Oid indexId, bool activate); + static bool reindexing = false; -extern bool + + +bool SetReindexProcessing(bool reindexmode) { bool old = reindexing; @@ -87,7 +89,8 @@ SetReindexProcessing(bool reindexmode) reindexing = reindexmode; return old; } -extern bool + +bool IsReindexProcessing(void) { return reindexing; @@ -154,14 +157,11 @@ GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp) } static TupleDesc -BuildFuncTupleDesc(FuncIndexInfo *funcInfo) +BuildFuncTupleDesc(Oid funcOid) { - HeapTuple tuple; TupleDesc funcTupDesc; + HeapTuple tuple; Oid retType; - char *funcname; - int4 nargs; - Oid *argtypes; /* * Allocate and zero a tuple descriptor. @@ -171,30 +171,29 @@ BuildFuncTupleDesc(FuncIndexInfo *funcInfo) MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE); /* - * Lookup the function for the return type. + * Lookup the function to get its name and return type. */ - funcname = FIgetname(funcInfo); - nargs = FIgetnArgs(funcInfo); - argtypes = FIgetArglist(funcInfo); - tuple = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(argtypes), - 0); - + tuple = SearchSysCacheTuple(PROCOID, + ObjectIdGetDatum(funcOid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - func_error("BuildFuncTupleDesc", funcname, nargs, argtypes, NULL); - + elog(ERROR, "Function %u does not exist", funcOid); retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; /* - * Look up the return type in pg_type for the type length. + * make the attributes name the same as the functions + */ + namestrcpy(&funcTupDesc->attrs[0]->attname, + NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname)); + + /* + * Lookup the return type in pg_type for the type length etc. */ tuple = SearchSysCacheTuple(TYPEOID, ObjectIdGetDatum(retType), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "Function %s return type does not exist", FIgetname(funcInfo)); + elog(ERROR, "Type %u does not exist", retType); /* * Assign some of the attributes values. Leave the rest as 0. @@ -208,57 +207,48 @@ BuildFuncTupleDesc(FuncIndexInfo *funcInfo) funcTupDesc->attrs[0]->attstorage = 'p'; funcTupDesc->attrs[0]->attalign = ((Form_pg_type) GETSTRUCT(tuple))->typalign; - /* - * make the attributes name the same as the functions - */ - namestrcpy(&funcTupDesc->attrs[0]->attname, funcname); - return funcTupDesc; } /* ---------------------------------------------------------------- * ConstructTupleDescriptor + * + * Build an index tuple descriptor for a new index (plain not functional) * ---------------------------------------------------------------- */ static TupleDesc ConstructTupleDescriptor(Oid heapoid, Relation heapRelation, - List *attributeList, int numatts, AttrNumber *attNums) { TupleDesc heapTupDesc; TupleDesc indexTupDesc; - IndexElem *IndexKey; - TypeName *IndexKeyType; - AttrNumber atnum; /* attributeNumber[attributeOffset] */ - AttrNumber atind; - int natts; /* Form_pg_class->relnatts */ - char *from; /* used to simplify memcpy below */ - char *to; /* used to simplify memcpy below */ + int natts; /* #atts in heap rel --- for error checks */ int i; + heapTupDesc = RelationGetDescr(heapRelation); + natts = RelationGetForm(heapRelation)->relnatts; + /* ---------------- * allocate the new tuple descriptor * ---------------- */ - natts = RelationGetForm(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) + for (i = 0; i < numatts; i++) { + AttrNumber atnum; /* attributeNumber[attributeOffset] */ + AttrNumber atind; + char *from; /* used to simplify memcpy below */ + char *to; /* used to simplify memcpy below */ /* ---------------- * get the attribute number and make sure it's valid @@ -268,16 +258,9 @@ ConstructTupleDescriptor(Oid heapoid, if (atnum > natts) elog(ERROR, "Cannot create index: attribute %d does not exist", atnum); - if (attributeList) - { - IndexKey = (IndexElem *) lfirst(attributeList); - IndexKeyType = IndexKey->typename; - attributeList = lnext(attributeList); - } - else - IndexKeyType = NULL; - indexTupDesc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); + indexTupDesc->attrs[i] = + (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); /* ---------------- * determine which tuple descriptor to copy @@ -285,10 +268,9 @@ ConstructTupleDescriptor(Oid heapoid, */ 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 + * here we are indexing on a system attribute (-1...-n) + * so we convert atnum into a usable index 0...n-1 so we can * use it to dereference the array sysatts[] which stores * tuple descriptor information for system attributes. * ---------------- @@ -298,7 +280,6 @@ ConstructTupleDescriptor(Oid heapoid, atind = (-atnum) - 1; from = (char *) (&sysatts[atind]); - } else { @@ -306,7 +287,6 @@ ConstructTupleDescriptor(Oid heapoid, * here we are indexing on a normal attribute (1...n) * ---------------- */ - heapTupDesc = RelationGetDescr(heapRelation); atind = AttrNumberGetAttrOffset(atnum); from = (char *) (heapTupDesc->attrs[atind]); @@ -317,43 +297,18 @@ ConstructTupleDescriptor(Oid heapoid, * the tuple desc data... * ---------------- */ - to = (char *) (indexTupDesc->attrs[i]); memcpy(to, from, ATTRIBUTE_TUPLE_SIZE); + /* + * Fix the stuff that should not be the same as the underlying attr + */ ((Form_pg_attribute) to)->attnum = i + 1; + ((Form_pg_attribute) to)->attdisbursion = 0.0; ((Form_pg_attribute) to)->attnotnull = false; ((Form_pg_attribute) to)->atthasdef = false; ((Form_pg_attribute) to)->attcacheoff = -1; - ((Form_pg_attribute) to)->atttypmod = -1; - ((Form_pg_attribute) to)->attalign = 'i'; - - /* - * 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(TYPENAME, - PointerGetDatum(IndexKeyType->name), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "create index: type '%s' undefined", - IndexKeyType->name); - ((Form_pg_attribute) to)->atttypid = tup->t_data->t_oid; - ((Form_pg_attribute) to)->attbyval = - ((Form_pg_type) GETSTRUCT(tup))->typbyval; - ((Form_pg_attribute) to)->attlen = - ((Form_pg_type) GETSTRUCT(tup))->typlen; - ((Form_pg_attribute) to)->attstorage = 'p'; - ((Form_pg_attribute) to)->attalign = - ((Form_pg_type) GETSTRUCT(tup))->typalign; - ((Form_pg_attribute) to)->atttypmod = IndexKeyType->typmod; - } - /* ---------------- * now we have to drop in the proper relation descriptor @@ -539,17 +494,14 @@ AppendAttributeTuples(Relation indexRelation, int numatts) new_tuple; 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, RowExclusiveLock); @@ -641,7 +593,6 @@ AppendAttributeTuples(Relation indexRelation, int numatts) heap_close(pg_attribute, RowExclusiveLock); if (hasind) CatalogCloseIndices(Num_pg_attr_indices, idescs); - } /* ---------------------------------------------------------------- @@ -651,18 +602,12 @@ AppendAttributeTuples(Relation indexRelation, int numatts) static void UpdateIndexRelation(Oid indexoid, Oid heapoid, - FuncIndexInfo *funcInfo, - int natts, - AttrNumber *attNums, + IndexInfo *indexInfo, Oid *classOids, - Node *predicate, - List *attributeList, bool islossy, - bool unique, bool primary) { Form_pg_index indexForm; - IndexElem *IndexKey; char *predString; text *predText; int predLen, @@ -673,13 +618,13 @@ UpdateIndexRelation(Oid indexoid, Relation idescs[Num_pg_index_indices]; /* ---------------- - * allocate an Form_pg_index big enough to hold the + * allocate a Form_pg_index big enough to hold the * index-predicate (if any) in string form * ---------------- */ - if (predicate != NULL) + if (indexInfo->ii_Predicate != NULL) { - predString = nodeToString(predicate); + predString = nodeToString(indexInfo->ii_Predicate); predText = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(predString))); pfree(predString); @@ -691,57 +636,33 @@ UpdateIndexRelation(Oid indexoid, predLen = VARSIZE(predText); itupLen = predLen + sizeof(FormData_pg_index); indexForm = (Form_pg_index) palloc(itupLen); - memset(indexForm, 0, sizeof(FormData_pg_index)); - - memmove((char *) &indexForm->indpred, (char *) predText, predLen); + MemSet(indexForm, 0, sizeof(FormData_pg_index)); /* ---------------- - * store the oid information into the index tuple form + * store information into the index tuple form * ---------------- */ - indexForm->indrelid = heapoid; indexForm->indexrelid = indexoid; - indexForm->indproc = (PointerIsValid(funcInfo)) ? - FIgetProcOid(funcInfo) : InvalidOid; + indexForm->indrelid = heapoid; + indexForm->indproc = indexInfo->ii_FuncOid; + indexForm->indisclustered = false; indexForm->indislossy = islossy; + indexForm->indhaskeytype = true; /* not actually used anymore */ + indexForm->indisunique = indexInfo->ii_Unique; indexForm->indisprimary = primary; - indexForm->indisunique = unique; - - indexForm->indhaskeytype = 0; - while (attributeList != NIL) - { - IndexKey = (IndexElem *) lfirst(attributeList); - if (IndexKey->typename != 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); + memcpy((char *) &indexForm->indpred, (char *) predText, predLen); /* ---------------- * copy index key and op class information + * + * We zeroed the extra slots (if any) above --- that's essential. * ---------------- */ - 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]; - } + for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++) + indexForm->indkey[i] = indexInfo->ii_KeyAttrNumbers[i]; - indexForm->indisclustered = '\0'; /* XXX constant */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + indexForm->indclass[i] = classOids[i]; /* ---------------- * open the system catalog index relation @@ -759,13 +680,12 @@ UpdateIndexRelation(Oid indexoid, /* ---------------- * insert the tuple into the pg_index - * XXX ADD INDEX TUPLES TOO * ---------------- */ heap_insert(pg_index, tuple); /* ---------------- - * insert the index tuple into the pg_index + * add index tuples for it * ---------------- */ if (!IsIgnoringSystemIndexes()) @@ -774,6 +694,7 @@ UpdateIndexRelation(Oid indexoid, CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple); CatalogCloseIndices(Num_pg_index_indices, idescs); } + /* ---------------- * close the relation and free the tuple * ---------------- @@ -923,6 +844,7 @@ InitIndexStrategy(int numatts, CommandCounterIncrement(); IndexSupportInitialize(strategy, support, + &indexRelation->rd_uniqueindex, attrelid, accessMethodObjectId, amstrategies, amsupport, numatts); @@ -941,15 +863,10 @@ InitIndexStrategy(int numatts, void index_create(char *heapRelationName, char *indexRelationName, - FuncIndexInfo *funcInfo, - List *attributeList, + IndexInfo *indexInfo, Oid accessMethodObjectId, - int numatts, - AttrNumber *attNums, Oid *classObjectId, - Node *predicate, bool islossy, - bool unique, bool primary, bool allow_system_table_mods) { @@ -958,16 +875,17 @@ index_create(char *heapRelationName, TupleDesc indexTupDesc; Oid heapoid; Oid indexoid; - PredInfo *predInfo; bool istemp = (get_temp_rel_by_username(heapRelationName) != NULL); char *temp_relname = NULL; + SetReindexProcessing(false); + /* ---------------- * check parameters * ---------------- */ - SetReindexProcessing(false); - if (numatts < 1) + if (indexInfo->ii_NumIndexAttrs < 1 || + indexInfo->ii_NumKeyAttrs < 1) elog(ERROR, "must index at least one attribute"); /* ---------------- @@ -985,14 +903,13 @@ index_create(char *heapRelationName, * construct new tuple descriptor * ---------------- */ - if (PointerIsValid(funcInfo)) - indexTupDesc = BuildFuncTupleDesc(funcInfo); + if (OidIsValid(indexInfo->ii_FuncOid)) + indexTupDesc = BuildFuncTupleDesc(indexInfo->ii_FuncOid); else indexTupDesc = ConstructTupleDescriptor(heapoid, heapRelation, - attributeList, - numatts, - attNums); + indexInfo->ii_NumKeyAttrs, + indexInfo->ii_KeyAttrNumbers); if (istemp) { @@ -1035,13 +952,15 @@ index_create(char *heapRelationName, * tuple forms in the index relation's tuple descriptor * ---------------- */ - InitializeAttributeOids(indexRelation, numatts, indexoid); + InitializeAttributeOids(indexRelation, + indexInfo->ii_NumIndexAttrs, + indexoid); /* ---------------- - * append ATTRIBUTE tuples + * append ATTRIBUTE tuples for the index * ---------------- */ - AppendAttributeTuples(indexRelation, numatts); + AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs); /* ---------------- * update pg_index @@ -1051,19 +970,16 @@ index_create(char *heapRelationName, * (Or, could define a rule to maintain the predicate) --Nels, Feb '92 * ---------------- */ - UpdateIndexRelation(indexoid, heapoid, funcInfo, - numatts, attNums, classObjectId, predicate, - attributeList, islossy, unique, primary); - - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = predicate; - predInfo->oldPred = NULL; + UpdateIndexRelation(indexoid, heapoid, indexInfo, + classObjectId, islossy, primary); /* ---------------- * initialize the index strategy * ---------------- */ - InitIndexStrategy(numatts, indexRelation, accessMethodObjectId); + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, + indexRelation, + accessMethodObjectId); /* * If this is bootstrap (initdb) time, then we don't actually fill in @@ -1078,14 +994,12 @@ index_create(char *heapRelationName, */ if (IsBootstrapProcessingMode()) { - index_register(heapRelationName, indexRelationName, numatts, attNums, - funcInfo, predInfo, unique); + index_register(heapRelationName, indexRelationName, indexInfo); /* XXX shouldn't we close the heap and index rels here? */ } else { - index_build(heapRelation, indexRelation, numatts, attNums, - funcInfo, predInfo, unique); + index_build(heapRelation, indexRelation, indexInfo, NULL); } } @@ -1238,43 +1152,163 @@ index_drop(Oid indexId) * index_build support * ---------------------------------------------------------------- */ + +/* ---------------- + * BuildIndexInfo + * Construct an IndexInfo record given the index's pg_index tuple + * + * IndexInfo stores the information about the index that's needed by + * FormIndexDatum, which is used for both index_build() and later insertion + * of individual index tuples. Normally we build an IndexInfo for an index + * just once per command, and then use it for (potentially) many tuples. + * ---------------- + */ +IndexInfo * +BuildIndexInfo(HeapTuple indexTuple) +{ + Form_pg_index indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); + IndexInfo *ii = makeNode(IndexInfo); + int i; + int numKeys; + + /* ---------------- + * count the number of keys, and copy them into the IndexInfo + * ---------------- + */ + numKeys = 0; + for (i = 0; i < INDEX_MAX_KEYS && + indexStruct->indkey[i] != InvalidAttrNumber; i++) + { + ii->ii_KeyAttrNumbers[i] = indexStruct->indkey[i]; + numKeys++; + } + ii->ii_NumKeyAttrs = numKeys; + + /* ---------------- + * Handle functional index. + * + * If we have a functional index then the number of + * attributes defined in the index must be 1 (the function's + * single return value). Otherwise it's same as number of keys. + * ---------------- + */ + ii->ii_FuncOid = indexStruct->indproc; + + if (OidIsValid(indexStruct->indproc)) + { + ii->ii_NumIndexAttrs = 1; + /* Do a lookup on the function, too */ + fmgr_info(indexStruct->indproc, & ii->ii_FuncInfo); + } + else + ii->ii_NumIndexAttrs = numKeys; + + /* ---------------- + * If partial index, convert predicate into expression nodetree + * ---------------- + */ + if (VARSIZE(&indexStruct->indpred) != 0) + { + char *predString; + + predString = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(&indexStruct->indpred))); + ii->ii_Predicate = stringToNode(predString); + pfree(predString); + } + else + ii->ii_Predicate = NULL; + + /* Other info */ + ii->ii_Unique = indexStruct->indisunique; + + return ii; +} + /* ---------------- * FormIndexDatum + * Construct Datum[] and nullv[] arrays for a new index tuple. + * + * indexInfo Info about the index + * heapTuple Heap tuple for which we must prepare an index entry + * heapDescriptor tupledesc for heap tuple + * resultCxt Temporary memory context for any palloc'd datums created + * datum Array of index Datums (output area) + * nullv Array of is-null indicators (output area) + * + * For largely historical reasons, we don't actually call index_formtuple() + * here, we just prepare its input arrays datum[] and nullv[]. * ---------------- */ void -FormIndexDatum(int numberOfAttributes, - AttrNumber *attributeNumber, +FormIndexDatum(IndexInfo *indexInfo, HeapTuple heapTuple, TupleDesc heapDescriptor, + MemoryContext resultCxt, Datum *datum, - char *nullv, - FuncIndexInfoPtr fInfo) + char *nullv) { - AttrNumber i; - int offset; + MemoryContext oldContext; + int i; + Datum iDatum; bool isNull; - /* ---------------- - * for each attribute we need from the heap tuple, - * get the attribute and stick it into the datum and - * null arrays. - * ---------------- - */ + oldContext = MemoryContextSwitchTo(resultCxt); - for (i = 1; i <= numberOfAttributes; i++) + if (OidIsValid(indexInfo->ii_FuncOid)) { - offset = AttrNumberGetAttrOffset(i); + /* ---------------- + * Functional index --- compute the single index attribute + * ---------------- + */ + FunctionCallInfoData fcinfo; + bool anynull = false; - datum[offset] = PointerGetDatum(GetIndexValue(heapTuple, - heapDescriptor, - offset, - attributeNumber, - fInfo, - &isNull)); + MemSet(&fcinfo, 0, sizeof(fcinfo)); + fcinfo.flinfo = &indexInfo->ii_FuncInfo; + fcinfo.nargs = indexInfo->ii_NumKeyAttrs; - nullv[offset] = (isNull) ? 'n' : ' '; + for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++) + { + fcinfo.arg[i] = heap_getattr(heapTuple, + indexInfo->ii_KeyAttrNumbers[i], + heapDescriptor, + &fcinfo.argnull[i]); + anynull |= fcinfo.argnull[i]; + } + if (indexInfo->ii_FuncInfo.fn_strict && anynull) + { + /* force a null result for strict function */ + iDatum = (Datum) 0; + isNull = true; + } + else + { + iDatum = FunctionCallInvoke(&fcinfo); + isNull = fcinfo.isnull; + } + datum[0] = iDatum; + nullv[0] = (isNull) ? 'n' : ' '; + } + else + { + /* ---------------- + * Plain index --- for each attribute we need from the heap tuple, + * get the attribute and stick it into the datum and nullv arrays. + * ---------------- + */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + { + iDatum = heap_getattr(heapTuple, + indexInfo->ii_KeyAttrNumbers[i], + heapDescriptor, + &isNull); + datum[i] = iDatum; + nullv[i] = (isNull) ? 'n' : ' '; + } } + + MemoryContextSwitchTo(oldContext); } @@ -1282,9 +1316,9 @@ FormIndexDatum(int numberOfAttributes, * Lock class info for update * -------------------------------------------- */ -static -bool -LockClassinfoForUpdate(Oid relid, HeapTuple rtup, Buffer *buffer, bool confirmCommitted) +static bool +LockClassinfoForUpdate(Oid relid, HeapTuple rtup, + Buffer *buffer, bool confirmCommitted) { HeapTuple classTuple; Form_pg_class pgcform; @@ -1429,7 +1463,7 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate) /* * Confirm that target tuple is locked by this transaction in case of - * immedaite updation. + * immediate updation. */ if (immediate) { @@ -1682,32 +1716,23 @@ UpdateStats(Oid relid, long reltuples, bool inplace) static void DefaultBuild(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, - AttrNumber *attributeNumber, - FuncIndexInfoPtr funcInfo, - PredInfo *predInfo, - bool unique, /* not used */ + IndexInfo *indexInfo, + Node *oldPred, IndexStrategy indexStrategy) /* not used */ { HeapScanDesc scan; HeapTuple heapTuple; - IndexTuple indexTuple; TupleDesc heapDescriptor; - TupleDesc indexDescriptor; - Datum *datum; - char *nullv; + Datum datum[INDEX_MAX_KEYS]; + char nullv[INDEX_MAX_KEYS]; long reltuples, indtuples; - + Node *predicate = indexInfo->ii_Predicate; #ifndef OMIT_PARTIAL_INDEX - ExprContext *econtext; TupleTable tupleTable; TupleTableSlot *slot; - #endif - Node *predicate; - Node *oldPred; - + ExprContext *econtext; InsertIndexResult insertResult; /* ---------------- @@ -1716,48 +1741,33 @@ DefaultBuild(Relation heapRelation, */ Assert(OidIsValid(indexRelation->rd_rel->relam)); /* XXX */ - /* ---------------- - * get the tuple descriptors from the relations so we know - * how to form the index tuples.. - * ---------------- - */ heapDescriptor = RelationGetDescr(heapRelation); - indexDescriptor = RelationGetDescr(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 + * 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 */ - - predicate = predInfo->pred; - oldPred = predInfo->oldPred; - #ifndef OMIT_PARTIAL_INDEX if (predicate != NULL || oldPred != NULL) { tupleTable = ExecCreateTupleTable(1); slot = ExecAllocTableSlot(tupleTable); ExecSetSlotDescriptor(slot, heapDescriptor); - econtext = MakeExprContext(slot, TransactionCommandContext); } else { tupleTable = NULL; slot = NULL; - econtext = NULL; } + econtext = MakeExprContext(slot, TransactionCommandContext); +#else + econtext = MakeExprContext(NULL, TransactionCommandContext); #endif /* OMIT_PARTIAL_INDEX */ /* ---------------- @@ -1781,6 +1791,8 @@ DefaultBuild(Relation heapRelation, */ while (HeapTupleIsValid(heapTuple = heap_getnext(scan, 0))) { + MemoryContextReset(econtext->ecxt_per_tuple_memory); + reltuples++; #ifndef OMIT_PARTIAL_INDEX @@ -1790,7 +1802,6 @@ DefaultBuild(Relation heapRelation, */ if (oldPred != NULL) { - /* SetSlotContents(slot, heapTuple); */ slot->val = heapTuple; if (ExecQual((List *) oldPred, econtext, false)) { @@ -1805,7 +1816,6 @@ DefaultBuild(Relation heapRelation, */ if (predicate != NULL) { - /* SetSlotContents(slot, heapTuple); */ slot->val = heapTuple; if (!ExecQual((List *) predicate, econtext, false)) continue; @@ -1819,26 +1829,18 @@ DefaultBuild(Relation heapRelation, * 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 */ - datum, /* return: array of attributes */ - nullv, /* return: array of char's */ - funcInfo); - - indexTuple = index_formtuple(indexDescriptor, - datum, - nullv); - - indexTuple->t_tid = heapTuple->t_self; + FormIndexDatum(indexInfo, + heapTuple, + heapDescriptor, + econtext->ecxt_per_tuple_memory, + datum, + nullv); insertResult = index_insert(indexRelation, datum, nullv, &(heapTuple->t_self), heapRelation); if (insertResult) pfree(insertResult); - pfree(indexTuple); } heap_endscan(scan); @@ -1846,14 +1848,10 @@ DefaultBuild(Relation heapRelation, #ifndef OMIT_PARTIAL_INDEX if (predicate != NULL || oldPred != NULL) { - /* parameter was 'false', almost certainly wrong --- tgl 9/21/99 */ ExecDropTupleTable(tupleTable, true); - FreeExprContext(econtext); } #endif /* OMIT_PARTIAL_INDEX */ - - pfree(nullv); - pfree(datum); + FreeExprContext(econtext); /* * Since we just counted the tuples in the heap, we update its stats @@ -1893,11 +1891,8 @@ DefaultBuild(Relation heapRelation, void index_build(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, - AttrNumber *attributeNumber, - FuncIndexInfo *funcInfo, - PredInfo *predInfo, - bool unique) + IndexInfo *indexInfo, + Node *oldPred) { RegProcedure procedure; @@ -1915,23 +1910,17 @@ index_build(Relation heapRelation, * ---------------- */ if (RegProcedureIsValid(procedure)) - OidFunctionCall8(procedure, + OidFunctionCall5(procedure, PointerGetDatum(heapRelation), PointerGetDatum(indexRelation), - Int32GetDatum(numberOfAttributes), - PointerGetDatum(attributeNumber), - PointerGetDatum(funcInfo), - PointerGetDatum(predInfo), - BoolGetDatum(unique), + PointerGetDatum(indexInfo), + PointerGetDatum(oldPred), PointerGetDatum(RelationGetIndexStrategy(indexRelation))); else DefaultBuild(heapRelation, indexRelation, - numberOfAttributes, - attributeNumber, - funcInfo, - predInfo, - unique, + indexInfo, + oldPred, RelationGetIndexStrategy(indexRelation)); } @@ -1959,34 +1948,9 @@ IndexGetRelation(Oid indexId) return index->indrelid; } -/* - * IndexIsUnique: given an index's relation OID, see if it - * is unique using the system cache. - */ -bool -IndexIsUnique(Oid indexId) -{ - HeapTuple tuple; - Form_pg_index index; - - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - elog(ERROR, "IndexIsUnique: can't find index id %u", - indexId); - } - index = (Form_pg_index) GETSTRUCT(tuple); - Assert(index->indexrelid == indexId); - - return index->indisunique; -} - - /* --------------------------------- * activate_index -- activate/deactivate the specified index. - * Note that currelntly PostgreSQL doesn't hold the + * Note that currently PostgreSQL doesn't hold the * status per index * --------------------------------- */ @@ -2011,92 +1975,47 @@ reindex_index(Oid indexId, bool force) ScanKeyData entry; HeapScanDesc scan; HeapTuple indexTuple, - procTuple, classTuple; - Form_pg_index index; + IndexInfo *indexInfo; Oid heapId, - procId, accessMethodId; - Node *oldPred = NULL; - PredInfo *predInfo; - AttrNumber *attributeNumberA; - FuncIndexInfo fInfo, - *funcInfo = NULL; - int i, - numberOfAttributes; - bool unique; - char *predString; bool old; old = SetReindexProcessing(true); - /* Scan pg_index to find indexes on heapRelation */ + + /* Scan pg_index to find the index's pg_index entry */ indexRelation = heap_openr(IndexRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indexrelid, F_OIDEQ, ObjectIdGetDatum(indexId)); scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry); indexTuple = heap_getnext(scan, 0); if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "reindex_index index %d tuple is invalid", indexId); - - /* - * For the index, fetch index attributes so we can apply index_build - */ - index = (Form_pg_index) GETSTRUCT(indexTuple); - heapId = index->indrelid; - procId = index->indproc; - unique = index->indisunique; - - for (i = 0; i < INDEX_MAX_KEYS; i++) - { - if (index->indkey[i] == InvalidAttrNumber) - break; - } - numberOfAttributes = i; + elog(ERROR, "reindex_index: index %u not found in pg_index", indexId); - /* If a valid where predicate, compute predicate Node */ - if (VARSIZE(&index->indpred) != 0) - { - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&index->indpred))); - oldPred = stringToNode(predString); - pfree(predString); - } - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = (Node *) oldPred; - predInfo->oldPred = NULL; + /* Get OID of index's parent table */ + heapId = ((Form_pg_index) GETSTRUCT(indexTuple))->indrelid; + /* Fetch info needed for index_build */ + indexInfo = BuildIndexInfo(indexTuple); - /* Assign Index keys to attributes array */ - attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * sizeof(AttrNumber)); - for (i = 0; i < numberOfAttributes; i++) - attributeNumberA[i] = index->indkey[i]; - - /* If this is a procedural index, initialize our FuncIndexInfo */ - if (procId != InvalidOid) - { - funcInfo = &fInfo; - FIsetnArgs(funcInfo, numberOfAttributes); - procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId), - 0, 0, 0); - if (!HeapTupleIsValid(procTuple)) - elog(ERROR, "RelationTruncateIndexes: index procedure not found"); - namecpy(&(funcInfo->funcName), - &(((Form_pg_proc) GETSTRUCT(procTuple))->proname)); - FIsetProcOid(funcInfo, procTuple->t_data->t_oid); - } + /* Complete the scan and close pg_index */ + heap_endscan(scan); + heap_close(indexRelation, AccessShareLock); /* Fetch the classTuple associated with this index */ - classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), 0, 0, 0); + classTuple = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(classTuple)) - elog(ERROR, "RelationTruncateIndexes: index access method not found"); + elog(ERROR, "reindex_index: index %u not found in pg_class", indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; /* Open our index relation */ - iRel = index_open(indexId); - if (iRel == NULL) - elog(ERROR, "reindex_index: can't open index relation"); heapRelation = heap_open(heapId, ExclusiveLock); if (heapRelation == NULL) elog(ERROR, "reindex_index: can't open heap relation"); + iRel = index_open(indexId); + if (iRel == NULL) + elog(ERROR, "reindex_index: can't open index relation"); /* Obtain exclusive lock on it, just to be sure */ LockRelation(iRel, AccessExclusiveLock); @@ -2112,23 +2031,16 @@ reindex_index(Oid indexId, bool force) iRel->rd_nblocks = 0; /* Initialize the index and rebuild */ - InitIndexStrategy(numberOfAttributes, iRel, accessMethodId); - index_build(heapRelation, iRel, numberOfAttributes, - attributeNumberA, funcInfo, predInfo, unique); + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId); + index_build(heapRelation, iRel, indexInfo, NULL); /* * index_build will close both the heap and index relations (but not - * give up the locks we hold on them). That's fine for the index, but - * we need to open the heap again. We need no new lock, since this - * backend still has the exclusive lock grabbed by heap_truncate. + * give up the locks we hold on them). So we're done. */ - iRel = index_open(indexId); - Assert(iRel != NULL); - /* Complete the scan and close pg_index */ - heap_endscan(scan); - heap_close(indexRelation, AccessShareLock); SetReindexProcessing(old); + return true; } diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index deb016e4a04e5e0b71a6427faf91c8a1d8252ba3..c2980f6fefc10b831206a8b18bc8d90985ec0e3b 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.66 2000/06/17 04:56:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.67 2000/07/14 22:17:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -83,9 +83,9 @@ static HeapTuple CatalogIndexFetchTuple(Relation heapRelation, /* - * Changes (appends) to catalogs can (and does) happen at various places + * Changes (appends) to catalogs can and do happen at various places * throughout the code. We need a generic routine that will open all of - * the indices defined on a given catalog a return the relation descriptors + * the indices defined on a given catalog and return the relation descriptors * associated with them. */ void @@ -115,9 +115,20 @@ CatalogCloseIndices(int nIndices, Relation *idescs) /* - * For the same reasons outlined above CatalogOpenIndices() we need a routine - * that takes a new catalog tuple and inserts an associated index tuple into - * each catalog index. + * For the same reasons outlined above for CatalogOpenIndices(), we need a + * routine that takes a new catalog tuple and inserts an associated index + * tuple into each catalog index. + * + * NOTE: since this routine looks up all the pg_index data on each call, + * it's relatively inefficient for inserting a large number of tuples into + * the same catalog. We use it only for inserting one or a few tuples + * in a given command. See ExecOpenIndices() and related routines if you + * are inserting tuples in bulk. + * + * NOTE: we do not bother to handle partial indices. Nor do we try to + * be efficient for functional indices (the code should work for them, + * but may leak memory intraquery). This should be OK for system catalogs, + * but don't use this routine for user tables! */ void CatalogIndexInsert(Relation *idescs, @@ -125,15 +136,9 @@ CatalogIndexInsert(Relation *idescs, Relation heapRelation, HeapTuple heapTuple) { - HeapTuple index_tup; TupleDesc heapDescriptor; - Form_pg_index index_form; Datum datum[INDEX_MAX_KEYS]; - char nulls[INDEX_MAX_KEYS]; - int natts; - AttrNumber *attnumP; - FuncIndexInfo finfo, - *finfoP; + char nullv[INDEX_MAX_KEYS]; int i; if (IsIgnoringSystemIndexes()) @@ -142,51 +147,30 @@ CatalogIndexInsert(Relation *idescs, for (i = 0; i < nIndices; i++) { + HeapTuple index_tup; + IndexInfo *indexInfo; InsertIndexResult indexRes; - index_tup = SearchSysCacheTupleCopy(INDEXRELID, - ObjectIdGetDatum(idescs[i]->rd_id), - 0, 0, 0); - Assert(index_tup); - index_form = (Form_pg_index) GETSTRUCT(index_tup); - - if (index_form->indproc != InvalidOid) - { - int fatts; - - /* - * Compute the number of attributes we are indexing upon. - */ - for (attnumP = index_form->indkey, fatts = 0; - fatts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber; - attnumP++, fatts++) - ; - FIgetnArgs(&finfo) = fatts; - natts = 1; - FIgetProcOid(&finfo) = index_form->indproc; - *(FIgetname(&finfo)) = '\0'; - finfoP = &finfo; - } - else - { - natts = RelationGetDescr(idescs[i])->natts; - finfoP = (FuncIndexInfo *) NULL; - } + index_tup = SearchSysCacheTuple(INDEXRELID, + ObjectIdGetDatum(idescs[i]->rd_id), + 0, 0, 0); + if (!HeapTupleIsValid(index_tup)) + elog(ERROR, "CatalogIndexInsert: index %u not found", + idescs[i]->rd_id); + indexInfo = BuildIndexInfo(index_tup); - FormIndexDatum(natts, - (AttrNumber *) index_form->indkey, + FormIndexDatum(indexInfo, heapTuple, heapDescriptor, + CurrentMemoryContext, datum, - nulls, - finfoP); + nullv); - indexRes = index_insert(idescs[i], datum, nulls, + indexRes = index_insert(idescs[i], datum, nullv, &heapTuple->t_self, heapRelation); if (indexRes) pfree(indexRes); - - heap_freetuple(index_tup); + pfree(indexInfo); } } diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 38539707cd8154f0028bc780c560bb62137f9b6a..5c176254d665cfe09877708145d6649dd57615d1 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 6648e66f4e398f73cc7a8be56bd25f5203f7898d..be24c696a7cb2328c7764dd0853fdf692f2242e2 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 355b218e6409a209fd0f194d24042619a7f9d449..52100e92dd92db72b0bc6c480b8df7d768e6fb37 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 efe8a44180a7554a091b28fed77b093e83532f40..6ede4f51c1234fbc9f594e01dcdc0f8562a1bfee 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,12 +115,21 @@ 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 */ @@ -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 71682baa8cd57df17b16d8a7a53c9caaa634bcd6..ee0ebeb4bb726e94dcfeafff687af50f18681400 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; } diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index daa40dccf75e7c188b2ba7c95935949634a56d52..39e3d5cd48bdbfd57c2b64e4c638c8d32ba3fc02 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.63 2000/07/12 02:37:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.64 2000/07/14 22:17:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,11 +27,9 @@ * QueryDescGetTypeInfo - moved here from main.c * am not sure what uses it -cim 10/12/89 * - * ExecGetIndexKeyInfo \ - * ExecOpenIndices | referenced by InitPlan, EndPlan, - * ExecCloseIndices | ExecAppend, ExecReplace - * ExecFormIndexTuple | - * ExecInsertIndexTuple / + * ExecOpenIndices \ + * ExecCloseIndices | referenced by InitPlan, EndPlan, + * ExecInsertIndexTuples / ExecAppend, ExecReplace * * NOTES * This file has traditionally been the place to stick misc. @@ -55,8 +53,6 @@ #include "utils/relcache.h" #include "utils/syscache.h" -static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP, - AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP); /* ---------------------------------------------------------------- * global counters for number of tuples processed, retrieved, @@ -684,93 +680,6 @@ QueryDescGetTypeInfo(QueryDesc *queryDesc) * ExecInsertIndexTuples support * ---------------------------------------------------------------- */ -/* ---------------------------------------------------------------- - * ExecGetIndexKeyInfo - * - * Extracts the index key attribute numbers from - * an index tuple form (i.e. a tuple from the pg_index relation) - * into an array of attribute numbers. The array and the - * size of the array are returned to the caller via return - * parameters. - * ---------------------------------------------------------------- - */ -static void -ExecGetIndexKeyInfo(Form_pg_index indexTuple, - int *numAttsOutP, - AttrNumber **attsOutP, - FuncIndexInfoPtr fInfoP) -{ - int i; - int numKeys; - AttrNumber *attKeys; - - /* ---------------- - * check parameters - * ---------------- - */ - if (numAttsOutP == NULL || attsOutP == NULL) - { - elog(DEBUG, "ExecGetIndexKeyInfo: %s", - "invalid parameters: numAttsOutP and attsOutP must be non-NULL"); - } - - /* ---------------- - * set the procid for a possible functional index. - * ---------------- - */ - FIsetProcOid(fInfoP, indexTuple->indproc); - - /* ---------------- - * count the number of keys.. - * ---------------- - */ - numKeys = 0; - for (i = 0; i < INDEX_MAX_KEYS && - indexTuple->indkey[i] != InvalidAttrNumber; i++) - numKeys++; - - /* ---------------- - * place number keys in callers return area - * or the number of arguments for a functional index. - * - * If we have a functional index then the number of - * attributes defined in the index must 1 (the function's - * single return value). - * ---------------- - */ - if (FIgetProcOid(fInfoP) != InvalidOid) - { - FIsetnArgs(fInfoP, numKeys); - (*numAttsOutP) = 1; - } - else - (*numAttsOutP) = numKeys; - - if (numKeys < 1) - { - elog(DEBUG, "ExecGetIndexKeyInfo: %s", - "all index key attribute numbers are zero!"); - (*attsOutP) = NULL; - return; - } - - /* ---------------- - * allocate and fill in array of key attribute numbers - * ---------------- - */ - CXT1_printf("ExecGetIndexKeyInfo: context is %d\n", CurrentMemoryContext); - - attKeys = (AttrNumber *) palloc(numKeys * sizeof(AttrNumber)); - - for (i = 0; i < numKeys; i++) - attKeys[i] = indexTuple->indkey[i]; - - /* ---------------- - * return array to caller. - * ---------------- - */ - (*attsOutP) = attKeys; -} /* ---------------------------------------------------------------- * ExecOpenIndices @@ -838,11 +747,6 @@ ExecOpenIndices(RelationInfo *resultRelationInfo) Oid indexOid = lfirsti(indexoidscan); Relation indexDesc; HeapTuple indexTuple; - Form_pg_index indexStruct; - int numKeyAtts; - AttrNumber *indexKeyAtts; - FuncIndexInfoPtr fInfoP; - PredInfo *predicate; IndexInfo *ii; /* ---------------- @@ -874,47 +778,17 @@ ExecOpenIndices(RelationInfo *resultRelationInfo) * Get the pg_index tuple for the index * ---------------- */ - indexTuple = SearchSysCacheTupleCopy(INDEXRELID, - ObjectIdGetDatum(indexOid), - 0, 0, 0); + indexTuple = SearchSysCacheTuple(INDEXRELID, + ObjectIdGetDatum(indexOid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "ExecOpenIndices: index %u not found", indexOid); - indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); /* ---------------- * extract the index key information from the tuple * ---------------- */ - fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP)); - ExecGetIndexKeyInfo(indexStruct, - &numKeyAtts, - &indexKeyAtts, - fInfoP); - - /* ---------------- - * next get the index predicate from the tuple - * ---------------- - */ - if (VARSIZE(&indexStruct->indpred) != 0) - { - char *predString; - - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&indexStruct->indpred))); - predicate = (PredInfo *) stringToNode(predString); - pfree(predString); - } - else - predicate = NULL; - - /* Save the index info */ - ii = makeNode(IndexInfo); - ii->ii_NumKeyAttributes = numKeyAtts; - ii->ii_KeyAttributeNumbers = indexKeyAtts; - ii->ii_FuncIndexInfo = fInfoP; - ii->ii_Predicate = (Node *) predicate; - - heap_freetuple(indexTuple); + ii = BuildIndexInfo(indexTuple); relationDescs[i] = indexDesc; indexInfoArray[i] = ii; @@ -984,17 +858,11 @@ ExecInsertIndexTuples(TupleTableSlot *slot, int numIndices; RelationPtr relationDescs; Relation heapRelation; + TupleDesc heapDescriptor; IndexInfo **indexInfoArray; - IndexInfo *indexInfo; - Node *predicate; ExprContext *econtext; - InsertIndexResult result; - int numberOfAttributes; - AttrNumber *keyAttributeNumbers; - FuncIndexInfoPtr fInfoP; - TupleDesc heapDescriptor; - Datum *datum; - char *nulls; + Datum datum[INDEX_MAX_KEYS]; + char nullv[INDEX_MAX_KEYS]; heapTuple = slot->val; @@ -1007,14 +875,27 @@ ExecInsertIndexTuples(TupleTableSlot *slot, relationDescs = resultRelationInfo->ri_IndexRelationDescs; indexInfoArray = resultRelationInfo->ri_IndexRelationInfo; heapRelation = resultRelationInfo->ri_RelationDesc; + heapDescriptor = RelationGetDescr(heapRelation); + + /* ---------------- + * Make a temporary expr/memory context for evaluating predicates + * and functional-index functions. + * XXX should do this once per command not once per tuple, and + * just reset it once per tuple. + * ---------------- + */ + econtext = MakeExprContext(slot, TransactionCommandContext); /* ---------------- * for each index, form and insert the index tuple * ---------------- */ - econtext = NULL; for (i = 0; i < numIndices; i++) { + IndexInfo *indexInfo; + Node *predicate; + InsertIndexResult result; + if (relationDescs[i] == NULL) continue; @@ -1022,39 +903,26 @@ ExecInsertIndexTuples(TupleTableSlot *slot, predicate = indexInfo->ii_Predicate; if (predicate != NULL) { - if (econtext == NULL) - econtext = MakeExprContext(slot, - TransactionCommandContext); - /* Skip this index-update if the predicate isn't satisfied */ if (!ExecQual((List *) predicate, econtext, false)) continue; } /* ---------------- - * get information from index info structure + * FormIndexDatum fills in its datum and null parameters + * with attribute information taken from the given heap tuple. * ---------------- */ - numberOfAttributes = indexInfo->ii_NumKeyAttributes; - keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers; - fInfoP = indexInfo->ii_FuncIndexInfo; - datum = (Datum *) palloc(numberOfAttributes * sizeof *datum); - nulls = (char *) palloc(numberOfAttributes * sizeof *nulls); - heapDescriptor = (TupleDesc) RelationGetDescr(heapRelation); - - FormIndexDatum(numberOfAttributes, /* num attributes */ - keyAttributeNumbers, /* array of att nums to - * extract */ - heapTuple, /* tuple from base relation */ - heapDescriptor, /* heap tuple's descriptor */ - datum, /* return: array of attributes */ - nulls, /* return: array of char's */ - fInfoP); /* functional index information */ - + FormIndexDatum(indexInfo, + heapTuple, + heapDescriptor, + econtext->ecxt_per_tuple_memory, + datum, + nullv); result = index_insert(relationDescs[i], /* index relation */ datum, /* array of heaptuple Datums */ - nulls, /* info on nulls */ + nullv, /* info on nulls */ &(heapTuple->t_self), /* tid of heap tuple */ heapRelation); @@ -1064,15 +932,11 @@ ExecInsertIndexTuples(TupleTableSlot *slot, */ IncrIndexInserted(); - /* ---------------- - * free index tuple after insertion - * ---------------- - */ if (result) pfree(result); } - if (econtext != NULL) - FreeExprContext(econtext); + + FreeExprContext(econtext); } void @@ -1094,5 +958,4 @@ SetChangedParamList(Plan *node, List *newchg) /* else - add this param to the list */ node->chgParam = lappendi(node->chgParam, paramId); } - } diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index cbf156267812c3abca9fd9ff487c434ee832bc3b..d8abfb4a2b7a23905b42f0d39f78a8091ab92270 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.73 2000/07/04 06:11:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.74 2000/07/14 22:17:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,12 +87,12 @@ static int _inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln); LargeObjectDesc * inv_create(int flags) { - int file_oid; LargeObjectDesc *retval; + Oid file_oid; Relation r; Relation indr; TupleDesc tupdesc; - AttrNumber attNums[1]; + IndexInfo *indexInfo; Oid classObjectId[1]; char objname[NAMEDATALEN]; char indname[NAMEDATALEN]; @@ -109,17 +109,13 @@ inv_create(int flags) sprintf(indname, "xinx%u", file_oid); if (RelnameFindRelid(objname) != InvalidOid) - { elog(ERROR, "internal error: %s already exists -- cannot create large obj", objname); - } if (RelnameFindRelid(indname) != InvalidOid) - { elog(ERROR, "internal error: %s already exists -- cannot create large obj", indname); - } /* this is pretty painful... want a tuple descriptor */ tupdesc = CreateTemplateTupleDesc(2); @@ -155,21 +151,25 @@ inv_create(int flags) /* * Now create a btree index on the relation's olastbyte attribute to - * make seeks go faster. The hardwired constants are embarassing to - * me, and are symptomatic of the pressure under which this code was - * written. - * - * ok, mao, let's put in some symbolic constants - jolly + * make seeks go faster. */ + 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; - attNums[0] = 1; classObjectId[0] = INT4_OPS_OID; - index_create(objname, indname, NULL, NULL, BTREE_AM_OID, - 1, &attNums[0], &classObjectId[0], - (Node *) NULL, false, false, false, false); + + index_create(objname, indname, indexInfo, + BTREE_AM_OID, classObjectId, + false, false, false); /* make the index visible in this transaction */ CommandCounterIncrement(); + indr = index_openr(indname); if (!RelationIsValid(indr)) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index c1cc688e8f61d430e80ba8f464dbde8e3d03155e..a7cb0ecac4998bfce06754fcfdffb318c20157ed 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.106 2000/07/05 23:11:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.107 2000/07/14 22:17:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1065,6 +1065,7 @@ IndexedAccessMethodInitialize(Relation relation) support = (RegProcedure *) NULL; IndexSupportInitialize(strategy, support, + &relation->rd_uniqueindex, relation->rd_att->attrs[0]->attrelid, relation->rd_rel->relam, relamstrategies, relamsupport, natts); diff --git a/src/include/access/funcindex.h b/src/include/access/funcindex.h deleted file mode 100644 index 0555755aaab7f26585a3bce4044b88cd5ea9dfba..0000000000000000000000000000000000000000 --- a/src/include/access/funcindex.h +++ /dev/null @@ -1,43 +0,0 @@ -/*------------------------------------------------------------------------- - * - * funcindex.h - * - * - * - * Portions Copyright (c) 1996-2000, PostgreSQL, Inc - * Portions Copyright (c) 1994, Regents of the University of California - * - * $Id: funcindex.h,v 1.9 2000/01/26 05:57:50 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#ifndef _FUNC_INDEX_INCLUDED_ -#define _FUNC_INDEX_INCLUDED_ - -typedef struct -{ - int nargs; - Oid arglist[FUNC_MAX_ARGS]; - Oid procOid; - NameData funcName; -} FuncIndexInfo; - -typedef FuncIndexInfo *FuncIndexInfoPtr; - -/* - * some marginally useful macro definitions - */ -/* #define FIgetname(FINFO) (&((FINFO)->funcName.data[0]))*/ -#define FIgetname(FINFO) (FINFO)->funcName.data -#define FIgetnArgs(FINFO) (FINFO)->nargs -#define FIgetProcOid(FINFO) (FINFO)->procOid -#define FIgetArg(FINFO, argnum) (FINFO)->arglist[argnum] -#define FIgetArglist(FINFO) (FINFO)->arglist - -#define FIsetnArgs(FINFO, numargs) ((FINFO)->nargs = numargs) -#define FIsetProcOid(FINFO, id) ((FINFO)->procOid = id) -#define FIsetArg(FINFO, argnum, argtype) ((FINFO)->arglist[argnum] = argtype) - -#define FIisFunctionalIndex(FINFO) (FINFO->procOid != InvalidOid) - -#endif /* FUNCINDEX_H */ diff --git a/src/include/access/genam.h b/src/include/access/genam.h index c7e0c5021b4b8b69bcaf97d2c788696aa79b5e7b..b62a979f051fe18fad6ba2b9c4492b770883b5d4 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,14 +7,13 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: genam.h,v 1.23 2000/01/26 05:57:50 momjian Exp $ + * $Id: genam.h,v 1.24 2000/07/14 22:17:53 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef GENAM_H #define GENAM_H -#include "access/funcindex.h" #include "access/itup.h" #include "access/relscan.h" #include "access/sdir.h" @@ -42,9 +41,6 @@ extern RetrieveIndexResult index_getnext(IndexScanDesc scan, extern RegProcedure index_cost_estimator(Relation relation); extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum); -extern Datum GetIndexValue(HeapTuple tuple, TupleDesc hTupDesc, - int attOff, AttrNumber *attrNums, FuncIndexInfo *fInfo, - bool *attNull); /* in genam.c */ extern IndexScanDesc RelationGetIndexScan(Relation relation, bool scanFromEnd, diff --git a/src/include/access/gist.h b/src/include/access/gist.h index dd8f557e9ba975c128846b66816cb95f1dedcc67..1297b02ff019c7e25fc08ce8916a78a4224c699e 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -12,7 +12,6 @@ #ifndef GIST_H #define GIST_H -#include "access/funcindex.h" #include "access/itup.h" #include "access/relscan.h" #include "access/sdir.h" diff --git a/src/include/access/hash.h b/src/include/access/hash.h index aa461a75e2b40ad8e23eadf8bbfd060e08d0786d..17d3496dee084c90a18ff74210dcf15d5c12b584 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: hash.h,v 1.34 2000/06/19 03:54:35 tgl Exp $ + * $Id: hash.h,v 1.35 2000/07/14 22:17:53 tgl Exp $ * * NOTES * modeled after Margo Seltzer's hash implementation for unix. @@ -17,7 +17,6 @@ #ifndef HASH_H #define HASH_H -#include "access/funcindex.h" #include "access/itup.h" #include "access/relscan.h" #include "access/sdir.h" diff --git a/src/include/access/istrat.h b/src/include/access/istrat.h index 99d4901bcdc989fbe6732e7799632b094022b3ee..9178f8c410e49a7b92de9a287279eb24355f2c48 100644 --- a/src/include/access/istrat.h +++ b/src/include/access/istrat.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: istrat.h,v 1.17 2000/06/08 22:37:36 momjian Exp $ + * $Id: istrat.h,v 1.18 2000/07/14 22:17:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,9 +56,12 @@ extern StrategyNumber RelationGetStrategy(Relation relation, AttrNumber attributeNumber, StrategyEvaluation evaluation, RegProcedure procedure); extern void IndexSupportInitialize(IndexStrategy indexStrategy, - RegProcedure *indexSupport, Oid indexObjectId, - Oid accessMethodObjectId, StrategyNumber maxStrategyNumber, - StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber); - + RegProcedure *indexSupport, + bool *isUnique, + Oid indexObjectId, + Oid accessMethodObjectId, + StrategyNumber maxStrategyNumber, + StrategyNumber maxSupportNumber, + AttrNumber maxAttributeNumber); #endif /* ISTRAT_H */ diff --git a/src/include/access/itup.h b/src/include/access/itup.h index e01cb7a31b628653f66234b1cb657c5d59c12a34..a5047729616ce140246533c24cda382f0338dafe 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: itup.h,v 1.24 2000/03/17 02:36:37 tgl Exp $ + * $Id: itup.h,v 1.25 2000/07/14 22:17:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,18 +61,6 @@ typedef struct RetrieveIndexResultData typedef RetrieveIndexResultData *RetrieveIndexResult; -/*----------------- - * PredInfo - - * used for partial indices - *----------------- - */ -typedef struct PredInfo -{ - Node *pred; - Node *oldPred; -} PredInfo; - - /* ---------------- * externs * ---------------- diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index b3ddea19d5078918d6179a2f6ce52ffbf46cbb70..882ac3c7d1cfd68c16b276027c314f91e74e5d44 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -7,18 +7,21 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: bootstrap.h,v 1.18 2000/06/17 23:41:49 tgl Exp $ + * $Id: bootstrap.h,v 1.19 2000/07/14 22:17:54 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef BOOTSTRAP_H #define BOOTSTRAP_H -#include "access/funcindex.h" #include "access/itup.h" +#include "nodes/execnodes.h" #include "utils/rel.h" -#define MAXATTR 40 /* max. number of attributes in a relation */ +/* MAXATTR is the maximum number of attributes in a relation supported + * at bootstrap time (ie, the max possible in a system table). + */ +#define MAXATTR 40 typedef struct hashnode { @@ -35,10 +38,7 @@ extern int DebugMode; extern int BootstrapMain(int ac, char *av[]); -extern void index_register(char *heap, char *ind, - int natts, AttrNumber *attnos, - FuncIndexInfo *finfo, PredInfo *predInfo, - bool unique); +extern void index_register(char *heap, char *ind, IndexInfo *indexInfo); extern void err_out(void); extern void InsertOneTuple(Oid objectid); diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 66b4f601be36d061065470636f7bdba0b998181e..e00b25e6f0758feb844a172ab5e2aa6455437360 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: index.h,v 1.28 2000/07/12 02:37:27 tgl Exp $ + * $Id: index.h,v 1.29 2000/07/14 22:17:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,25 +27,24 @@ extern void InitIndexStrategy(int numatts, Oid accessMethodObjectId); extern void index_create(char *heapRelationName, - char *indexRelationName, - FuncIndexInfo *funcInfo, - List *attributeList, - Oid accessMethodObjectId, - int numatts, - AttrNumber *attNums, - Oid *classObjectId, - Node *predicate, - bool islossy, - bool unique, - bool primary, - bool allow_system_table_mods); + char *indexRelationName, + IndexInfo *indexInfo, + Oid accessMethodObjectId, + Oid *classObjectId, + bool islossy, + bool primary, + bool allow_system_table_mods); extern void index_drop(Oid indexId); -extern void FormIndexDatum(int numberOfAttributes, - AttrNumber *attributeNumber, HeapTuple heapTuple, - TupleDesc heapDescriptor, Datum *datum, - char *nullv, FuncIndexInfoPtr fInfo); +extern IndexInfo *BuildIndexInfo(HeapTuple indexTuple); + +extern void FormIndexDatum(IndexInfo *indexInfo, + HeapTuple heapTuple, + TupleDesc heapDescriptor, + MemoryContext resultCxt, + Datum *datum, + char *nullv); extern void UpdateStats(Oid relid, long reltuples, bool inplace); extern bool IndexesAreActive(Oid relid, bool comfirmCommitted); @@ -54,11 +53,7 @@ extern bool SetReindexProcessing(bool processing); extern bool IsReindexProcessing(void); extern void index_build(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, AttrNumber *attributeNumber, - FuncIndexInfo *funcInfo, PredInfo *predInfo, - bool unique); - -extern bool IndexIsUnique(Oid indexId); + IndexInfo *indexInfo, Node *oldPred); extern bool reindex_index(Oid indexId, bool force); extern bool activate_indexes_of_a_table(Oid relid, bool activate); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index bd260a827b47440414a4c2d08f3538f148b486d3..538299773d96afc37d658779ff64758b926b9f50 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.146 2000/07/08 03:04:21 tgl Exp $ + * $Id: pg_proc.h,v 1.147 2000/07/14 22:17:56 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -677,7 +677,7 @@ DATA(insert OID = 321 ( rtdelete PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 DESCR("r-tree(internal)"); DATA(insert OID = 322 ( rtgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 rtgettuple - )); DESCR("r-tree(internal)"); -DATA(insert OID = 323 ( rtbuild PGUID 12 f t f t 8 f 23 "0 0 0 0 0 0 0 0" 100 0 0 100 rtbuild - )); +DATA(insert OID = 323 ( rtbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 rtbuild - )); DESCR("r-tree(internal)"); DATA(insert OID = 324 ( rtbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 rtbeginscan - )); DESCR("r-tree(internal)"); @@ -706,7 +706,7 @@ DATA(insert OID = 336 ( btmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 DESCR("btree(internal)"); DATA(insert OID = 337 ( btrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 btrestrpos - )); DESCR("btree(internal)"); -DATA(insert OID = 338 ( btbuild PGUID 12 f t f t 8 f 23 "0 0 0 0 0 0 0 0" 100 0 0 100 btbuild - )); +DATA(insert OID = 338 ( btbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 btbuild - )); DESCR("btree(internal)"); DATA(insert OID = 339 ( poly_same PGUID 11 f t t t 2 f 16 "604 604" 100 0 1 0 poly_same - )); @@ -810,7 +810,7 @@ DATA(insert OID = 446 ( hashmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 DESCR("hash(internal)"); DATA(insert OID = 447 ( hashrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 hashrestrpos - )); DESCR("hash(internal)"); -DATA(insert OID = 448 ( hashbuild PGUID 12 f t f t 8 f 23 "0 0 0 0 0 0 0 0" 100 0 0 100 hashbuild - )); +DATA(insert OID = 448 ( hashbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 hashbuild - )); DESCR("hash(internal)"); DATA(insert OID = 449 ( hashint2 PGUID 12 f t t t 1 f 23 "21" 100 0 0 100 hashint2 - )); DESCR("hash"); @@ -1033,7 +1033,7 @@ DATA(insert OID = 780 ( gistmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 DESCR("gist(internal)"); DATA(insert OID = 781 ( gistrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 gistrestrpos - )); DESCR("gist(internal)"); -DATA(insert OID = 782 ( gistbuild PGUID 12 f t f t 8 f 23 "0 0 0 0 0 0 0 0" 100 0 0 100 gistbuild - )); +DATA(insert OID = 782 ( gistbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 gistbuild - )); DESCR("gist(internal)"); DATA(insert OID = 784 ( tintervaleq PGUID 12 f t f t 2 f 16 "704 704" 100 0 0 100 tintervaleq - )); diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index fed4c6a9a1691a544d14b3c51d9f9d5267a122c4..b42a8e6a17f8cec9fb9ff61b122a452b7258962f 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -7,17 +7,16 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: vacuum.h,v 1.31 2000/05/29 17:40:44 momjian Exp $ + * $Id: vacuum.h,v 1.32 2000/07/14 22:17:57 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef VACUUM_H #define VACUUM_H -#include "fmgr.h" -#include "access/funcindex.h" -#include "catalog/pg_index.h" #include "catalog/pg_attribute.h" +#include "catalog/pg_index.h" +#include "fmgr.h" #include "nodes/pg_list.h" #include "storage/itemptr.h" @@ -54,14 +53,6 @@ typedef struct VacPageListData typedef VacPageListData *VacPageList; -typedef struct -{ - FuncIndexInfo finfo; - FuncIndexInfo *finfoP; - Form_pg_index tform; - int natts; -} IndDesc; - typedef struct { Form_pg_attribute attr; diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 2c21dba9c237acfcc1735b41630a44e62a388878..62a887d754ba3c77a6a1d52e11fa88733fcd2112 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,39 +7,49 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execnodes.h,v 1.43 2000/07/12 02:37:32 tgl Exp $ + * $Id: execnodes.h,v 1.44 2000/07/14 22:17:58 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef EXECNODES_H #define EXECNODES_H -#include "access/funcindex.h" #include "access/relscan.h" #include "access/sdir.h" #include "executor/hashjoin.h" #include "executor/tuptable.h" +#include "fmgr.h" #include "nodes/params.h" #include "nodes/primnodes.h" /* ---------------- * IndexInfo information * - * this class holds the information saying what attributes - * are the key attributes for this index. -cim 10/15/89 - * - * NumKeyAttributes number of key attributes for this index - * KeyAttributeNumbers array of attribute numbers used as keys - * Predicate partial-index predicate for this index + * this class holds the information needed to construct new index + * entries for a particular index. Used for both index_build and + * retail creation of index entries. + * + * NumIndexAttrs number of columns in this index + * (1 if a func. index, else same as NumKeyAttrs) + * NumKeyAttrs number of key attributes for this index + * (ie, number of attrs from underlying relation) + * KeyAttrNumbers underlying-rel attribute numbers used as keys + * Predicate partial-index predicate, or NULL if none + * FuncOid OID of function, or InvalidOid if not f. index + * FuncInfo fmgr lookup data for function, if FuncOid valid + * Unique is it a unique index? * ---------------- */ typedef struct IndexInfo { NodeTag type; - int ii_NumKeyAttributes; - AttrNumber *ii_KeyAttributeNumbers; - FuncIndexInfoPtr ii_FuncIndexInfo; + int ii_NumIndexAttrs; + int ii_NumKeyAttrs; + AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]; Node *ii_Predicate; + Oid ii_FuncOid; + FmgrInfo ii_FuncInfo; + bool ii_Unique; } IndexInfo; /* ---------------- diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 121012d7fd4984bf61683ec5fcfec04e9bd8a2f5..c90ba3c5ee0900e0d2ceb860dac9176bfe685211 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rel.h,v 1.39 2000/06/30 07:04:03 tgl Exp $ + * $Id: rel.h,v 1.40 2000/07/14 22:18:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -92,6 +92,7 @@ typedef struct RelationData bool rd_isnailed; /* rel is nailed in cache */ bool rd_unlinked; /* rel already unlinked or not created yet */ bool rd_indexfound; /* true if rd_indexlist is valid */ + bool rd_uniqueindex; /* true if rel is a UNIQUE index */ Form_pg_am rd_am; /* AM tuple */ Form_pg_class rd_rel; /* RELATION tuple */ Oid rd_id; /* relation's object id */