diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c index eb66d41bf26e43e31a1cef92b0141cca0791d34a..26112171911213701e5f77a5d97b58d36eff4496 100644 --- a/src/backend/access/common/scankey.c +++ b/src/backend/access/common/scankey.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.19 2001/06/01 02:41:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.20 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,3 +69,31 @@ ScanKeyEntryInitialize(ScanKey entry, Assert(ScanKeyEntryIsLegal(entry)); } + +/* + * ScanKeyEntryInitializeWithInfo + * Initializes a scan key entry using an already-completed FmgrInfo + * function lookup record. + * + * mcxt is the memory context holding the scan key; it'll be used for + * any subsidiary info attached to the scankey's FmgrInfo record. + */ +void +ScanKeyEntryInitializeWithInfo(ScanKey entry, + bits16 flags, + AttrNumber attributeNumber, + FmgrInfo *finfo, + MemoryContext mcxt, + Datum argument) +{ + Assert(PointerIsValid(entry)); + Assert(RegProcedureIsValid(finfo->fn_oid)); + + entry->sk_flags = flags; + entry->sk_attno = attributeNumber; + entry->sk_procedure = finfo->fn_oid; + entry->sk_argument = argument; + fmgr_info_copy(&entry->sk_func, finfo, mcxt); + + Assert(ScanKeyEntryIsLegal(entry)); +} diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index e05e07b6366522d8daf2af00e9445b63723db4be..4a702fe31741a8088611e0fbcd80462d689de5c0 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.83 2001/08/22 18:24:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.84 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1542,13 +1542,6 @@ gistbulkdelete(PG_FUNCTION_ARGS) void initGISTstate(GISTSTATE *giststate, Relation index) { - RegProcedure consistent_proc, - union_proc, - compress_proc, - decompress_proc, - penalty_proc, - picksplit_proc, - equal_proc; int i; if (index->rd_att->natts > INDEX_MAX_KEYS) @@ -1559,20 +1552,27 @@ initGISTstate(GISTSTATE *giststate, Relation index) for (i = 0; i < index->rd_att->natts; i++) { - consistent_proc = index_getprocid(index, i+1, GIST_CONSISTENT_PROC ); - union_proc = index_getprocid(index, i+1, GIST_UNION_PROC ); - compress_proc = index_getprocid(index, i+1, GIST_COMPRESS_PROC ); - decompress_proc = index_getprocid(index, i+1, GIST_DECOMPRESS_PROC ); - penalty_proc = index_getprocid(index, i+1, GIST_PENALTY_PROC ); - picksplit_proc = index_getprocid(index, i+1, GIST_PICKSPLIT_PROC ); - equal_proc = index_getprocid(index, i+1, GIST_EQUAL_PROC ); - fmgr_info(consistent_proc, &((giststate->consistentFn)[i]) ); - fmgr_info(union_proc, &((giststate->unionFn)[i]) ); - fmgr_info(compress_proc, &((giststate->compressFn)[i]) ); - fmgr_info(decompress_proc, &((giststate->decompressFn)[i]) ); - fmgr_info(penalty_proc, &((giststate->penaltyFn)[i]) ); - fmgr_info(picksplit_proc, &((giststate->picksplitFn)[i]) ); - fmgr_info(equal_proc, &((giststate->equalFn)[i]) ); + fmgr_info_copy(&(giststate->consistentFn[i]), + index_getprocinfo(index, i+1, GIST_CONSISTENT_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->unionFn[i]), + index_getprocinfo(index, i+1, GIST_UNION_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->compressFn[i]), + index_getprocinfo(index, i+1, GIST_COMPRESS_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->decompressFn[i]), + index_getprocinfo(index, i+1, GIST_DECOMPRESS_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->penaltyFn[i]), + index_getprocinfo(index, i+1, GIST_PENALTY_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->picksplitFn[i]), + index_getprocinfo(index, i+1, GIST_PICKSPLIT_PROC), + CurrentMemoryContext); + fmgr_info_copy(&(giststate->equalFn[i]), + index_getprocinfo(index, i+1, GIST_EQUAL_PROC), + CurrentMemoryContext); } } diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 0aac61fa025dcba02d98fcfc75eae6c2d90813a2..4680061118375f2d79c5ae779559e00d19635fd1 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.26 2001/02/22 21:48:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.27 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/genam.h" #include "access/hash.h" #include "access/iqual.h" @@ -27,8 +28,8 @@ _hash_mkscankey(Relation rel, IndexTuple itup, HashMetaPage metap) int natts; AttrNumber i; Datum arg; - RegProcedure proc; - bool null; + FmgrInfo *procinfo; + bool isnull; natts = rel->rd_rel->relnatts; itupdesc = RelationGetDescr(rel); @@ -37,10 +38,14 @@ _hash_mkscankey(Relation rel, IndexTuple itup, HashMetaPage metap) for (i = 0; i < natts; i++) { - arg = index_getattr(itup, i + 1, itupdesc, &null); - proc = metap->hashm_procid; - ScanKeyEntryInitialize(&skey[i], - 0x0, (AttrNumber) (i + 1), proc, arg); + arg = index_getattr(itup, i + 1, itupdesc, &isnull); + procinfo = index_getprocinfo(rel, i + 1, HASHPROC); + ScanKeyEntryInitializeWithInfo(&skey[i], + 0x0, + (AttrNumber) (i + 1), + procinfo, + CurrentMemoryContext, + arg); } return skey; @@ -89,10 +94,13 @@ _hash_formitem(IndexTuple itup) Bucket _hash_call(Relation rel, HashMetaPage metap, Datum key) { + FmgrInfo *procinfo; uint32 n; Bucket bucket; - n = DatumGetUInt32(OidFunctionCall1(metap->hashm_procid, key)); + /* XXX assumes index has only one attribute */ + procinfo = index_getprocinfo(rel, 1, HASHPROC); + n = DatumGetUInt32(FunctionCall1(procinfo, key)); bucket = n & metap->hashm_highmask; if (bucket > metap->hashm_maxbucket) bucket = bucket & metap->hashm_lowmask; diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 2b6be06168f234cec7865e46f858e2074bb74c70..2a1d3294dd0d446ae777bdea16f096f3af7bb7d1 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.52 2001/07/15 22:48:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.53 2001/10/06 23:21:43 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relationId @@ -428,12 +428,58 @@ index_getprocid(Relation irel, { RegProcedure *loc; int nproc; + int procindex; nproc = irel->rd_am->amsupport; + Assert(procnum > 0 && procnum <= (uint16) nproc); + + procindex = (nproc * (attnum - 1)) + (procnum - 1); + loc = irel->rd_support; Assert(loc != NULL); - return loc[(nproc * (attnum - 1)) + (procnum - 1)]; + return loc[procindex]; +} + +/* ---------------- + * index_getprocinfo + * + * This routine allows index AMs to keep fmgr lookup info for + * support procs in the relcache. + * ---------------- + */ +struct FmgrInfo * +index_getprocinfo(Relation irel, + AttrNumber attnum, + uint16 procnum) +{ + FmgrInfo *locinfo; + int nproc; + int procindex; + + nproc = irel->rd_am->amsupport; + + Assert(procnum > 0 && procnum <= (uint16) nproc); + + procindex = (nproc * (attnum - 1)) + (procnum - 1); + + locinfo = irel->rd_supportinfo; + + Assert(locinfo != NULL); + + locinfo += procindex; + + /* Initialize the lookup info if first time through */ + if (locinfo->fn_oid == InvalidOid) + { + RegProcedure *loc = irel->rd_support; + + Assert(loc != NULL); + + fmgr_info_cxt(loc[procindex], locinfo, irel->rd_indexcxt); + } + + return locinfo; } diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c index 35df06aeace8eda1ffcc255b67474d70ed24360b..568581fc18acfdbb98db164334ef64ad92166290 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.52 2001/08/21 16:36:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.53 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -486,12 +486,9 @@ FillScanKeyEntry(Oid operatorObjectId, ScanKey entry) operatorObjectId); /* - * Formerly we initialized entry->sk_func here, but that's a waste of - * time because ScanKey entries in strategy maps are never actually - * used to invoke the operator. Furthermore, to do that we'd have to - * worry about setting the proper memory context (the map is probably - * not allocated in the current memory context!) + * Mark entry->sk_func invalid, until and unless someone sets it up. */ + entry->sk_func.fn_oid = InvalidOid; } diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 295387ed5177a0d9c2e10c2b7c21657e9160b9f1..86ff810845c4d6a37483307df008f4cdc0d8d934 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.67 2001/07/15 22:48:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.68 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -435,7 +435,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) BlockNumber blkno; StrategyNumber strat; RetrieveIndexResult res; - RegProcedure proc; int32 result; BTScanOpaque so; bool continuescan; @@ -532,6 +531,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) scankeys = (ScanKey) palloc(keysCount * sizeof(ScanKeyData)); for (i = 0; i < keysCount; i++) { + FmgrInfo *procinfo; + j = nKeyIs[i]; /* @@ -545,9 +546,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet"); return ((RetrieveIndexResult) NULL); } - proc = index_getprocid(rel, i + 1, BTORDER_PROC); - ScanKeyEntryInitialize(scankeys + i, so->keyData[j].sk_flags, - i + 1, proc, so->keyData[j].sk_argument); + procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); + ScanKeyEntryInitializeWithInfo(scankeys + i, + so->keyData[j].sk_flags, + i + 1, + procinfo, + CurrentMemoryContext, + so->keyData[j].sk_argument); } if (nKeyIs) pfree(nKeyIs); diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 28aa99237d298eaad5b4022f3b167d624503b71f..86d2e3cf8fa7a0cf04b028e399ec2469401fc538 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.45 2001/05/17 14:59:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.46 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup) TupleDesc itupdesc; int natts; int i; - RegProcedure proc; + FmgrInfo *procinfo; Datum arg; bool null; bits16 flag; @@ -48,14 +48,15 @@ _bt_mkscankey(Relation rel, IndexTuple itup) for (i = 0; i < natts; i++) { - proc = index_getprocid(rel, i + 1, BTORDER_PROC); + procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); arg = index_getattr(itup, i + 1, itupdesc, &null); flag = null ? SK_ISNULL : 0x0; - ScanKeyEntryInitialize(&skey[i], - flag, - (AttrNumber) (i + 1), - proc, - arg); + ScanKeyEntryInitializeWithInfo(&skey[i], + flag, + (AttrNumber) (i + 1), + procinfo, + CurrentMemoryContext, + arg); } return skey; @@ -76,7 +77,7 @@ _bt_mkscankey_nodata(Relation rel) ScanKey skey; int natts; int i; - RegProcedure proc; + FmgrInfo *procinfo; natts = RelationGetNumberOfAttributes(rel); @@ -84,12 +85,13 @@ _bt_mkscankey_nodata(Relation rel) for (i = 0; i < natts; i++) { - proc = index_getprocid(rel, i + 1, BTORDER_PROC); - ScanKeyEntryInitialize(&skey[i], - SK_ISNULL, - (AttrNumber) (i + 1), - proc, - (Datum) NULL); + procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); + ScanKeyEntryInitializeWithInfo(&skey[i], + SK_ISNULL, + (AttrNumber) (i + 1), + procinfo, + CurrentMemoryContext, + (Datum) 0); } return skey; diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c index f3b46f3144bac23c754aa037bae8cc119a5bcba0..42878248b0002546513e8e682f7dc393a6ea385f 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.64 2001/09/29 03:46:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.65 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1264,17 +1264,15 @@ rtbulkdelete(PG_FUNCTION_ARGS) static void initRtstate(RTSTATE *rtstate, Relation index) { - RegProcedure union_proc, - size_proc, - inter_proc; - - union_proc = index_getprocid(index, 1, RT_UNION_PROC); - size_proc = index_getprocid(index, 1, RT_SIZE_PROC); - inter_proc = index_getprocid(index, 1, RT_INTER_PROC); - fmgr_info(union_proc, &rtstate->unionFn); - fmgr_info(size_proc, &rtstate->sizeFn); - fmgr_info(inter_proc, &rtstate->interFn); - return; + fmgr_info_copy(&rtstate->unionFn, + index_getprocinfo(index, 1, RT_UNION_PROC), + CurrentMemoryContext); + fmgr_info_copy(&rtstate->sizeFn, + index_getprocinfo(index, 1, RT_SIZE_PROC), + CurrentMemoryContext); + fmgr_info_copy(&rtstate->interFn, + index_getprocinfo(index, 1, RT_INTER_PROC), + CurrentMemoryContext); } /* for sorting SPLITCOST records in descending order */ diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index b68488ae0073c69adbff99636cb8bf706e279959..599e79a4ea67104ede684ade962c711b860b7f96 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.176 2001/09/06 02:07:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.177 2001/10/06 23:21:43 tgl Exp $ * * * INTERFACE ROUTINES @@ -973,10 +973,8 @@ RelationTruncateIndexes(Oid heapId) while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { - Oid indexId, - accessMethodId; + Oid indexId; IndexInfo *indexInfo; - HeapTuple classTuple; Relation heapRelation, currentIndex; @@ -986,16 +984,6 @@ RelationTruncateIndexes(Oid heapId) indexId = ((Form_pg_index) GETSTRUCT(indexTuple))->indexrelid; indexInfo = BuildIndexInfo(indexTuple); - /* Fetch access method from pg_class tuple for this index */ - classTuple = SearchSysCache(RELOID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - if (!HeapTupleIsValid(classTuple)) - elog(ERROR, "RelationTruncateIndexes: index %u not found in pg_class", - indexId); - accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; - ReleaseSysCache(classTuple); - /* * We have to re-open the heap rel each time through this loop * because index_build will close it again. We need grab no lock, @@ -1022,8 +1010,6 @@ RelationTruncateIndexes(Oid heapId) currentIndex->rd_targblock = InvalidBlockNumber; /* Initialize the index and rebuild */ - InitIndexStrategy(indexInfo->ii_NumIndexAttrs, - currentIndex, accessMethodId); index_build(heapRelation, currentIndex, indexInfo); /* diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index c850c55a0f50f202c5e0a7ac69b2f8d2fcb318f3..b53eab86524a5a4769475988f3a9005e23f0b856 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.164 2001/09/26 21:09:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.165 2001/10/06 23:21:43 tgl Exp $ * * * INTERFACE ROUTINES @@ -644,76 +644,6 @@ UpdateIndexRelation(Oid indexoid, heap_freetuple(tuple); } -/* ---------------------------------------------------------------- - * InitIndexStrategy - * - * XXX this is essentially the same as relcache.c's - * IndexedAccessMethodInitialize(), and probably ought to be merged with it. - * ---------------------------------------------------------------- - */ -void -InitIndexStrategy(int numatts, - Relation indexRelation, - Oid accessMethodObjectId) -{ - IndexStrategy strategy; - RegProcedure *support; - uint16 amstrategies; - uint16 amsupport; - Size strsize; - - /* - * get information from the index relation descriptor - */ - amstrategies = indexRelation->rd_am->amstrategies; - amsupport = indexRelation->rd_am->amsupport; - - /* - * compute the size of the strategy array - */ - strsize = AttributeNumberGetIndexStrategySize(numatts, amstrategies); - - /* - * allocate the new index strategy structure - * - * the index strategy has to be allocated in the same context as the - * relation descriptor cache or else it will be lost at the end of the - * transaction. - */ - if (!CacheMemoryContext) - CreateCacheMemoryContext(); - - strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext, - strsize); - - if (amsupport > 0) - { - strsize = numatts * (amsupport * sizeof(RegProcedure)); - support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext, - strsize); - } - else - support = (RegProcedure *) NULL; - - /* - * fill in the index strategy structure with information from the - * catalogs. First we must advance the command counter so that we - * will see the newly-entered index catalog tuples. - */ - CommandCounterIncrement(); - - IndexSupportInitialize(strategy, support, - &indexRelation->rd_uniqueindex, - RelationGetRelid(indexRelation), - accessMethodObjectId, - amstrategies, amsupport, numatts); - - /* - * store the strategy information in the index reldesc - */ - RelationSetIndexSupport(indexRelation, strategy, support); -} - /* ---------------------------------------------------------------- * index_create @@ -839,11 +769,13 @@ index_create(char *heapRelationName, classObjectId, primary); /* - * initialize the index strategy + * fill in the index strategy structure with information from the + * catalogs. First we must advance the command counter so that we + * will see the newly-entered index catalog tuples. */ - InitIndexStrategy(indexInfo->ii_NumIndexAttrs, - indexRelation, - accessMethodObjectId); + CommandCounterIncrement(); + + RelationInitIndexAccessInfo(indexRelation); /* * If this is bootstrap (initdb) time, then we don't actually fill in @@ -1935,11 +1867,9 @@ reindex_index(Oid indexId, bool force, bool inplace) heapRelation; ScanKeyData entry; HeapScanDesc scan; - HeapTuple indexTuple, - classTuple; + HeapTuple indexTuple; IndexInfo *indexInfo; - Oid heapId, - accessMethodId; + Oid heapId; bool old; /* @@ -1970,15 +1900,6 @@ reindex_index(Oid indexId, bool force, bool inplace) heap_endscan(scan); heap_close(indexRelation, AccessShareLock); - /* Fetch the classTuple associated with this index */ - classTuple = SearchSysCache(RELOID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - if (!HeapTupleIsValid(classTuple)) - elog(ERROR, "reindex_index: index %u not found in pg_class", indexId); - accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; - ReleaseSysCache(classTuple); - /* Open our index relation */ heapRelation = heap_open(heapId, ExclusiveLock); if (heapRelation == NULL) @@ -2012,7 +1933,6 @@ reindex_index(Oid indexId, bool force, bool inplace) } /* Initialize the index and rebuild */ - InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId); index_build(heapRelation, iRel, indexInfo); /* diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index c15476217551d2b25f66bc199934fc37fc50bd2a..e83d35edbf669044bac91ee1222513a3072bb5ce 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.60 2001/10/02 21:39:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.61 2001/10/06 23:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -246,11 +246,14 @@ ProcedureCreate(char *procedureName, if (languageObjectId == ClanguageId) { + void *libraryhandle; + /* If link symbol is specified as "-", substitute procedure name */ if (strcmp(prosrc, "-") == 0) prosrc = procedureName; - (void) load_external_function(probin, prosrc, true); - (void) fetch_finfo_record(probin, prosrc); + (void) load_external_function(probin, prosrc, true, + &libraryhandle); + (void) fetch_finfo_record(libraryhandle, prosrc); } /* diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index ebbb8b07ee8f14ba933aa65a5667ea9368f532a1..a03ca7744081e7f5ba844dca69fef8d78cc92265 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group * Copyright 1999 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.27 2001/10/05 17:28:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.28 2001/10/06 23:21:44 tgl Exp $ * * ---------- */ @@ -3243,7 +3243,6 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) { HeapTuple opr_tup; Oid opr_proc; - MemoryContext oldcontext; FmgrInfo finfo; opr_tup = SearchSysCache(OPERNAME, @@ -3265,9 +3264,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) * table entry, we must make sure any subsidiary structures of the * fmgr record are kept in TopMemoryContext. */ - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(opr_proc, &finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(opr_proc, &finfo, TopMemoryContext); entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache, (void *) &typeid, diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index d75d05309df38153ed2c9a58f8f2f440f17496c9..a294bfc9fff96c1a7de33d7f6ef9b1ad2fff32a2 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.18 2001/05/22 16:37:16 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.19 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "catalog/pg_type.h" #include "utils/array.h" #include "utils/fmgroids.h" +#include "utils/memutils.h" #include "utils/varbit.h" #define HEXDIG(z) ((z)<10 ? ((z)+'0') : ((z)-10+'A')) @@ -238,7 +239,7 @@ _bit(PG_FUNCTION_ARGS) static FmgrInfo bit_finfo; if (bit_finfo.fn_oid == InvalidOid) - fmgr_info(F_BIT, &bit_finfo); + fmgr_info_cxt(F_BIT, &bit_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &bit_finfo; @@ -452,7 +453,7 @@ _varbit(PG_FUNCTION_ARGS) static FmgrInfo varbit_finfo; if (varbit_finfo.fn_oid == InvalidOid) - fmgr_info(F_VARBIT, &varbit_finfo); + fmgr_info_cxt(F_VARBIT, &varbit_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &varbit_finfo; diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 7ed56e7962f3712f6c2d48258cd9936f67189809..c963709ac8f6bddc35f21b40551b35b396a349b0 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.83 2001/10/03 05:29:24 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.84 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -285,7 +285,7 @@ _bpchar(PG_FUNCTION_ARGS) static FmgrInfo bpchar_finfo; if (bpchar_finfo.fn_oid == InvalidOid) - fmgr_info(F_BPCHAR, &bpchar_finfo); + fmgr_info_cxt(F_BPCHAR, &bpchar_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &bpchar_finfo; @@ -544,7 +544,7 @@ _varchar(PG_FUNCTION_ARGS) static FmgrInfo varchar_finfo; if (varchar_finfo.fn_oid == InvalidOid) - fmgr_info(F_VARCHAR, &varchar_finfo); + fmgr_info_cxt(F_VARCHAR, &varchar_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &varchar_finfo; diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile index 01896efdd338b4d3d8367b0cc087df240a72219c..5ac5a06827cb1fc01af67d5737f9b29e368f23ee 100644 --- a/src/backend/utils/cache/Makefile +++ b/src/backend/utils/cache/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/cache # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.14 2000/08/31 16:10:46 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.15 2001/10/06 23:21:44 tgl Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/utils/cache top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = catcache.o inval.o rel.o relcache.o syscache.o lsyscache.o \ +OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \ fcache.o temprel.o all: SUBSYS.o diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index ce4363706b3513032f77440fffb63b787168ec33..77112a694e72fe1cc0c2ae447f8614085918fa1c 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.82 2001/08/21 16:36:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.83 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -269,23 +269,10 @@ CatalogCacheInitializeCache(CatCache *cache) */ cache->cc_skey[i].sk_procedure = EQPROC(keytype); - /* - * Note: to avoid any possible leakage of scan temporary data into - * the cache context, we do not switch into CacheMemoryContext while - * calling fmgr_info here. Instead set fn_mcxt on return. This - * would fail to work correctly if fmgr_info allocated any subsidiary - * data structures to attach to the FmgrInfo record; but it doesn't - * do so for built-in functions, and all the comparator functions - * for system caches should most assuredly be built-in functions. - * Currently there's no real need to fix fn_mcxt either, but let's do - * that anyway just to make sure it's not pointing to a dead context - * later on. - */ - - fmgr_info(cache->cc_skey[i].sk_procedure, - &cache->cc_skey[i].sk_func); - - cache->cc_skey[i].sk_func.fn_mcxt = CacheMemoryContext; + /* Do function lookup */ + fmgr_info_cxt(cache->cc_skey[i].sk_procedure, + &cache->cc_skey[i].sk_func, + CacheMemoryContext); /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */ cache->cc_skey[i].sk_attno = cache->cc_key[i]; diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c index bb1ac36f3efdf3715e438074fd7d2ca288804866..92cf46a036d85aa05b40b4aeaccc550bc6435148 100644 --- a/src/backend/utils/cache/fcache.c +++ b/src/backend/utils/cache/fcache.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.40 2001/09/21 00:11:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.41 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,26 +23,22 @@ FunctionCachePtr init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt) { - MemoryContext oldcontext; FunctionCachePtr retval; /* Safety check (should never fail, as parser should check sooner) */ if (nargs > FUNC_MAX_ARGS) elog(ERROR, "init_fcache: too many arguments"); - /* Switch to a context long-lived enough for the fcache entry */ - oldcontext = MemoryContextSwitchTo(fcacheCxt); - - retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); + /* Create fcache entry in the desired context */ + retval = (FunctionCachePtr) MemoryContextAlloc(fcacheCxt, + sizeof(FunctionCache)); MemSet(retval, 0, sizeof(FunctionCache)); /* Set up the primary fmgr lookup information */ - fmgr_info(foid, &(retval->func)); + fmgr_info_cxt(foid, &(retval->func), fcacheCxt); /* Initialize additional info */ retval->setArgsValid = false; - MemoryContextSwitchTo(oldcontext); - return retval; } diff --git a/src/backend/utils/cache/rel.c b/src/backend/utils/cache/rel.c deleted file mode 100644 index 588566afc402835d9c552ff44e536e8fcffba530..0000000000000000000000000000000000000000 --- a/src/backend/utils/cache/rel.c +++ /dev/null @@ -1,49 +0,0 @@ -/*------------------------------------------------------------------------- - * - * rel.c - * POSTGRES relation descriptor code. - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.9 2001/01/24 19:43:15 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" -#include "access/istrat.h" - - -/* - * RelationIsValid is now a macro in rel.h -cim 4/27/91 - * - * All of the RelationGet...() functions are now macros in rel.h - * -mer 3/2/92 - */ - -/* - * RelationSetIndexSupport - * Sets index strategy and support info for a relation. - * - * This routine saves two pointers -- one to the IndexStrategy, and - * one to the RegProcs that support the indexed access method. - * - * Note: - * Assumes relation descriptor is valid. - * Assumes index strategy is valid. Assumes support is valid if non- - * NULL. - */ -void -RelationSetIndexSupport(Relation relation, - IndexStrategy strategy, - RegProcedure *support) -{ - Assert(PointerIsValid(relation)); - Assert(IndexStrategyIsValid(strategy)); - - relation->rd_istrat = strategy; - relation->rd_support = support; -} diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 8d8548713943a43e0ed33c08bb1f9ddc266a7611..c56d606076a48e86ae8e59fa2548a2a2b8b15f03 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.145 2001/10/05 17:28:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.146 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -249,7 +249,6 @@ static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, Relation relation); static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, Relation oldrelation); -static void IndexedAccessMethodInitialize(Relation relation); static void AttrDefaultFetch(Relation relation); static void RelCheckFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); @@ -1044,7 +1043,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, * initialize index strategy and support information for this relation */ if (OidIsValid(relam)) - IndexedAccessMethodInitialize(relation); + RelationInitIndexAccessInfo(relation); /* * initialize the relation lock manager information @@ -1087,41 +1086,75 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, return relation; } -static void -IndexedAccessMethodInitialize(Relation relation) +/* + * Initialize index-access-method support data for an index relation + */ +void +RelationInitIndexAccessInfo(Relation relation) { + MemoryContext indexcxt; IndexStrategy strategy; RegProcedure *support; + FmgrInfo *supportinfo; int natts; - Size stratSize; - Size supportSize; uint16 amstrategies; uint16 amsupport; + Size stratSize; natts = relation->rd_rel->relnatts; amstrategies = relation->rd_am->amstrategies; amsupport = relation->rd_am->amsupport; + /* + * Make the private context to hold index access info. The reason + * we need a context, and not just a couple of pallocs, is so that + * we won't leak any subsidiary info attached to fmgr lookup records. + * + * Context parameters are set on the assumption that it'll probably not + * contain much data. + */ + indexcxt = AllocSetContextCreate(CacheMemoryContext, + RelationGetRelationName(relation), + 0, /* minsize */ + 512, /* initsize */ + 1024); /* maxsize */ + relation->rd_indexcxt = indexcxt; + + /* + * Allocate arrays to hold data + */ stratSize = AttributeNumberGetIndexStrategySize(natts, amstrategies); - strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext, - stratSize); + strategy = (IndexStrategy) MemoryContextAlloc(indexcxt, stratSize); if (amsupport > 0) { - supportSize = natts * (amsupport * sizeof(RegProcedure)); - support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext, - supportSize); + int nsupport = natts * amsupport; + + support = (RegProcedure *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(RegProcedure)); + supportinfo = (FmgrInfo *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo)); + MemSet(supportinfo, 0, nsupport * sizeof(FmgrInfo)); } else - support = (RegProcedure *) NULL; + { + support = NULL; + supportinfo = NULL; + } + /* + * Fill the strategy map and the support RegProcedure arrays. + * (supportinfo is left as zeroes, and is filled on-the-fly when used) + */ IndexSupportInitialize(strategy, support, &relation->rd_uniqueindex, RelationGetRelid(relation), relation->rd_rel->relam, amstrategies, amsupport, natts); - RelationSetIndexSupport(relation, strategy, support); + relation->rd_istrat = strategy; + relation->rd_support = support; + relation->rd_supportinfo = supportinfo; } /* @@ -1595,11 +1628,9 @@ RelationClearRelation(Relation relation, bool rebuildIt) pfree(relation->rd_am); if (relation->rd_rel) pfree(relation->rd_rel); - if (relation->rd_istrat) - pfree(relation->rd_istrat); - if (relation->rd_support) - pfree(relation->rd_support); freeList(relation->rd_indexlist); + if (relation->rd_indexcxt) + MemoryContextDelete(relation->rd_indexcxt); /* * If we're really done with the relcache entry, blow it away. But if @@ -2624,8 +2655,11 @@ init_irels(void) Relation ird; Form_pg_am am; Form_pg_class relform; + MemoryContext indexcxt; IndexStrategy strat; RegProcedure *support; + int nstrategies, + nsupport; int i; int relno; @@ -2646,6 +2680,13 @@ init_irels(void) return; } + /* safety check for incompatible relcache layout */ + if (len != sizeof(RelationData)) + { + write_irels(); + return; + } + ird = irel[relno] = (Relation) palloc(len); MemSet(ird, 0, len); @@ -2659,6 +2700,7 @@ init_irels(void) /* reset transient fields */ ird->rd_targblock = InvalidBlockNumber; ird->rd_fd = -1; + ird->rd_refcnt = 0; ird->rd_node.tblNode = MyDatabaseId; @@ -2716,6 +2758,17 @@ init_irels(void) } } + /* + * prepare index info context --- parameters should match + * RelationInitIndexAccessInfo + */ + indexcxt = AllocSetContextCreate(CacheMemoryContext, + RelationGetRelationName(ird), + 0, /* minsize */ + 512, /* initsize */ + 1024); /* maxsize */ + ird->rd_indexcxt = indexcxt; + /* next, read the index strategy map */ if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len)) { @@ -2723,27 +2776,18 @@ init_irels(void) return; } - strat = (IndexStrategy) palloc(len); + strat = (IndexStrategy) MemoryContextAlloc(indexcxt, len); if ((nread = FileRead(fd, (char *) strat, len)) != len) { write_irels(); return; } - /* oh, for god's sake... */ -#define SMD(i) strat->strategyMapData[i].entry[0] - - /* have to reinit the function pointers in the strategy maps */ - for (i = 0; i < am->amstrategies * relform->relnatts; i++) - { - fmgr_info(SMD(i).sk_procedure, - &(SMD(i).sk_func)); - } + /* have to invalidate any FmgrInfo data in the strategy maps */ + nstrategies = am->amstrategies * relform->relnatts; + for (i = 0; i < nstrategies; i++) + strat->strategyMapData[i].entry[0].sk_func.fn_oid = InvalidOid; - /* - * use a real field called rd_istrat instead of the bogosity of - * hanging invisible fields off the end of a structure - jolly - */ ird->rd_istrat = strat; /* finally, read the vector of support procedures */ @@ -2753,7 +2797,7 @@ init_irels(void) return; } - support = (RegProcedure *) palloc(len); + support = (RegProcedure *) MemoryContextAlloc(indexcxt, len); if ((nread = FileRead(fd, (char *) support, len)) != len) { write_irels(); @@ -2761,6 +2805,11 @@ init_irels(void) } ird->rd_support = support; + nsupport = relform->relnatts * am->amsupport; + ird->rd_supportinfo = (FmgrInfo *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo)); + MemSet(ird->rd_supportinfo, 0, nsupport * sizeof(FmgrInfo)); + RelationInitLockInfo(ird); RelationCacheInsert(ird); diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index f46d40c5c481764bef71cf56edfe7045133adf22..3085187d8a941f3c2344ecabc0040f1e6b5b3355 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.52 2001/10/04 19:13:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.53 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,14 +55,20 @@ static char * substitute_libpath_macro(const char * name); /* * Load the specified dynamic-link library file, and look for a function - * named funcname in it. If the function is not found, we raise an error - * if signalNotFound is true, else return (PGFunction) NULL. Note that - * errors in loading the library will provoke elog regardless of - * signalNotFound. - */ + * named funcname in it. (funcname can be NULL to just load the file.) + * + * If the function is not found, we raise an error if signalNotFound is true, + * else return (PGFunction) NULL. Note that errors in loading the library + * will provoke elog regardless of signalNotFound. + * + * If filehandle is not NULL, then *filehandle will be set to a handle + * identifying the library file. The filehandle can be used with + * lookup_external_function to lookup additional functions in the same file + * at less cost than repeating load_external_function. + */ PGFunction load_external_function(char *filename, char *funcname, - bool signalNotFound) + bool signalNotFound, void **filehandle) { DynamicFileList *file_scanner; PGFunction retval; @@ -130,6 +136,10 @@ load_external_function(char *filename, char *funcname, file_tail = file_scanner; } + /* Return handle if caller wants it. */ + if (filehandle) + *filehandle = file_scanner->handle; + /* * If funcname is NULL, we only wanted to load the file. */ @@ -201,11 +211,20 @@ load_file(char *filename) } } - load_external_function(fullname, (char *) NULL, false); + load_external_function(fullname, (char *) NULL, false, (void *) NULL); pfree(fullname); } +/* + * Lookup a function whose library file is already loaded. + * Return (PGFunction) NULL if not found. + */ +PGFunction +lookup_external_function(void *filehandle, char *funcname) +{ + return pg_dlsym(filehandle, funcname); +} static bool @@ -305,7 +324,7 @@ substitute_libpath_macro(const char * name) AssertArg(name != NULL); - if (strlen(name) == 0 || name[0] != '$') + if (name[0] != '$') return pstrdup(name); macroname_len = strcspn(name + 1, "/") + 1; diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 45ca532de249a9cf7d85737e699f1ece2f6b7672..5faa8a155c1b907ef1254292cde9b2d881c4bf9f 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.54 2001/08/14 22:21:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.55 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -121,11 +121,21 @@ fmgr_lookupByName(const char *name) * will be allocated in that context. The caller must ensure that this * context is at least as long-lived as the info struct itself. This is * not a problem in typical cases where the info struct is on the stack or - * in freshly-palloc'd space, but one must take extra care when the info - * struct is in a long-lived table. + * in freshly-palloc'd space. However, if one intends to store an info + * struct in a long-lived table, it's better to use fmgr_info_cxt. */ void fmgr_info(Oid functionId, FmgrInfo *finfo) +{ + fmgr_info_cxt(functionId, finfo, CurrentMemoryContext); +} + +/* + * Fill a FmgrInfo struct, specifying a memory context in which its + * subsidiary data should go. + */ +void +fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt) { const FmgrBuiltin *fbp; HeapTuple procedureTuple; @@ -139,7 +149,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) */ finfo->fn_oid = InvalidOid; finfo->fn_extra = NULL; - finfo->fn_mcxt = CurrentMemoryContext; + finfo->fn_mcxt = mcxt; if ((fbp = fmgr_isbuiltin(functionId)) != NULL) { @@ -228,6 +238,7 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) probinattr; char *prosrcstring, *probinstring; + void *libraryhandle; PGFunction user_fn; Pg_finfo_record *inforec; Oldstyle_fnextra *fnextra; @@ -250,22 +261,19 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr)); /* Look up the function itself */ - user_fn = load_external_function(probinstring, prosrcstring, true); + user_fn = load_external_function(probinstring, prosrcstring, true, + &libraryhandle); /* Get the function information record (real or default) */ - inforec = fetch_finfo_record(probinstring, prosrcstring); + inforec = fetch_finfo_record(libraryhandle, prosrcstring); switch (inforec->api_version) { case 0: /* Old style: need to use a handler */ finfo->fn_addr = fmgr_oldstyle; - - /* - * OK to use palloc here because fn_mcxt is - * CurrentMemoryContext - */ - fnextra = (Oldstyle_fnextra *) palloc(sizeof(Oldstyle_fnextra)); + fnextra = (Oldstyle_fnextra *) + MemoryContextAlloc(finfo->fn_mcxt, sizeof(Oldstyle_fnextra)); finfo->fn_extra = (void *) fnextra; MemSet(fnextra, 0, sizeof(Oldstyle_fnextra)); fnextra->func = (func_ptr) user_fn; @@ -335,6 +343,8 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) /* * Fetch and validate the information record for the given external function. + * The function is specified by a handle for the containing library + * (obtained from load_external_function) as well as the function name. * * If no info function exists for the given name, it is not an error. * Instead we return a default info record for a version-0 function. @@ -346,7 +356,7 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) * pg_proc. */ Pg_finfo_record * -fetch_finfo_record(char *filename, char *funcname) +fetch_finfo_record(void *filehandle, char *funcname) { char *infofuncname; PGFInfoFunction infofunc; @@ -355,12 +365,12 @@ fetch_finfo_record(char *filename, char *funcname) /* Compute name of info func */ infofuncname = (char *) palloc(strlen(funcname) + 10); - sprintf(infofuncname, "pg_finfo_%s", funcname); + strcpy(infofuncname, "pg_finfo_"); + strcat(infofuncname, funcname); /* Try to look up the info function */ - infofunc = (PGFInfoFunction) load_external_function(filename, - infofuncname, - false); + infofunc = (PGFInfoFunction) lookup_external_function(filehandle, + infofuncname); if (infofunc == (PGFInfoFunction) NULL) { /* Not found --- assume version 0 */ @@ -391,6 +401,34 @@ fetch_finfo_record(char *filename, char *funcname) } +/* + * Copy an FmgrInfo struct + * + * This is inherently somewhat bogus since we can't reliably duplicate + * language-dependent subsidiary info. We cheat by zeroing fn_extra, + * instead, meaning that subsidiary info will have to be recomputed. + */ +void +fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, + MemoryContext destcxt) +{ + memcpy(dstinfo, srcinfo, sizeof(FmgrInfo)); + dstinfo->fn_mcxt = destcxt; + if (dstinfo->fn_addr == fmgr_oldstyle) + { + /* For oldstyle functions we must copy fn_extra */ + Oldstyle_fnextra *fnextra; + + fnextra = (Oldstyle_fnextra *) + MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra)); + memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra)); + dstinfo->fn_extra = (void *) fnextra; + } + else + dstinfo->fn_extra = NULL; +} + + /* * Specialized lookup routine for ProcedureCreate(): given the alleged name * of an internal function, return the OID of the function. diff --git a/src/include/access/genam.h b/src/include/access/genam.h index db6795c0933e1bd554a53932e6ab13d32cbb895d..0a70691e770ac5cdf1bbcea03f1471bc826660f1 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: genam.h,v 1.26 2001/07/15 22:48:18 tgl Exp $ + * $Id: genam.h,v 1.27 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,6 +56,8 @@ extern IndexBulkDeleteResult *index_bulk_delete(Relation relation, extern RegProcedure index_cost_estimator(Relation relation); extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum); +extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, + uint16 procnum); /* in genam.c */ extern IndexScanDesc RelationGetIndexScan(Relation relation, bool scanFromEnd, diff --git a/src/include/access/skey.h b/src/include/access/skey.h index 4e49f51afb1cc86b4178e589e5d35dc440726c03..304d5e4a46232f624b9f32bce39123e173533c98 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: skey.h,v 1.16 2001/06/09 18:16:59 tgl Exp $ + * $Id: skey.h,v 1.17 2001/10/06 23:21:44 tgl Exp $ * * Note: * Needs more accessor/assignment routines. @@ -44,5 +44,8 @@ typedef ScanKeyData *ScanKey; extern void ScanKeyEntrySetIllegal(ScanKey entry); extern void ScanKeyEntryInitialize(ScanKey entry, bits16 flags, AttrNumber attributeNumber, RegProcedure procedure, Datum argument); +extern void ScanKeyEntryInitializeWithInfo(ScanKey entry, bits16 flags, + AttrNumber attributeNumber, FmgrInfo *finfo, + MemoryContext mcxt, Datum argument); #endif /* SKEY_H */ diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index d3e3bae7048377e829dc9ff31eacfda265162eae..52956f807b3d6621634fc08c523dbf2121db74f8 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: index.h,v 1.39 2001/08/21 16:36:05 tgl Exp $ + * $Id: index.h,v 1.40 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,10 +30,6 @@ typedef void (*IndexBuildCallback) (Relation index, extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId, MemoryContext resultCxt); -extern void InitIndexStrategy(int numatts, - Relation indexRelation, - Oid accessMethodObjectId); - extern Oid index_create(char *heapRelationName, char *indexRelationName, IndexInfo *indexInfo, diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 44641bdcb1829dab3f070500a4cb2655a51ebf5c..0acb966f683362987b176f30855844ba770d9915 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: fmgr.h,v 1.14 2001/05/17 17:44:18 petere Exp $ + * $Id: fmgr.h,v 1.15 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,7 +35,7 @@ typedef Datum (*PGFunction) (FunctionCallInfo fcinfo); * to be called multiple times, the lookup need be done only once and the * info struct saved for re-use. */ -typedef struct +typedef struct FmgrInfo { PGFunction fn_addr; /* pointer to function or handler to be * called */ @@ -72,6 +72,20 @@ typedef struct FunctionCallInfoData */ extern void fmgr_info(Oid functionId, FmgrInfo *finfo); +/* + * Same, when the FmgrInfo struct is in a memory context longer-lived than + * CurrentMemoryContext. The specified context will be set as fn_mcxt + * and used to hold all subsidiary data of finfo. + */ +extern void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, + MemoryContext mcxt); + +/* + * Copy an FmgrInfo struct + */ +extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, + MemoryContext destcxt); + /* * This macro invokes a function given a filled-in FunctionCallInfoData * struct. The macro result is the returned Datum --- but note that @@ -341,16 +355,18 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2, /* * Routines in fmgr.c */ -extern Pg_finfo_record *fetch_finfo_record(char *filename, char *funcname); +extern Pg_finfo_record *fetch_finfo_record(void *filehandle, char *funcname); extern Oid fmgr_internal_function(const char *proname); /* * Routines in dfmgr.c */ +extern char * Dynamic_library_path; + extern PGFunction load_external_function(char *filename, char *funcname, - bool signalNotFound); + bool signalNotFound, void **filehandle); +extern PGFunction lookup_external_function(void *filehandle, char *funcname); extern void load_file(char *filename); -extern char * Dynamic_library_path; /* diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index ef74317fda500ce5e769dbe2e45df58abb20253e..9cc7a2ecb47e02ceaed4ba590a433c113a90cbdd 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rel.h,v 1.51 2001/06/27 23:31:40 tgl Exp $ + * $Id: rel.h,v 1.52 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,8 +23,6 @@ #include "storage/fd.h" #include "storage/relfilenode.h" -/* added to prevent circular dependency. bjm 1999/11/15 */ -extern char *get_temp_rel_by_physicalname(const char *relname); /* * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient @@ -115,7 +113,7 @@ typedef struct RelationData bool rd_isnailed; /* rel is nailed in cache */ 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_am rd_am; /* AM tuple (if an index) */ Form_pg_class rd_rel; /* RELATION tuple */ Oid rd_id; /* relation's object id */ List *rd_indexlist; /* list of OIDs of indexes on relation */ @@ -123,10 +121,16 @@ typedef struct RelationData TupleDesc rd_att; /* tuple descriptor */ RuleLock *rd_rules; /* rewrite rules */ MemoryContext rd_rulescxt; /* private memory cxt for rd_rules, if any */ - IndexStrategy rd_istrat; /* info needed if rel is an index */ - RegProcedure *rd_support; TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */ + /* index access support info (used only for an index relation) */ + MemoryContext rd_indexcxt; /* private memory cxt for this stuff */ + IndexStrategy rd_istrat; /* operator strategy map */ + RegProcedure *rd_support; /* OIDs of support procedures */ + struct FmgrInfo *rd_supportinfo; /* lookup info for support procedures */ + /* "struct FmgrInfo" avoids need to include fmgr.h here */ + + /* statistics collection area */ PgStat_Info pgstat_info; } RelationData; @@ -228,13 +232,6 @@ typedef Relation *RelationPtr; */ #define RelationGetIndexStrategy(relation) ((relation)->rd_istrat) -/* - * Routines in utils/cache/rel.c - */ -extern void RelationSetIndexSupport(Relation relation, - IndexStrategy strategy, - RegProcedure *support); - /* * Handle temp relations */ @@ -279,5 +276,7 @@ extern void RelationSetIndexSupport(Relation relation, RelationGetPhysicalRelationName(relation) \ ) +/* added to prevent circular dependency. bjm 1999/11/15 */ +extern char *get_temp_rel_by_physicalname(const char *relname); #endif /* REL_H */ diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 160ee0f47c721ce6e6f8f8b754f819f5ee348ce3..861185cea9e1772cde813a23239b48e85a249783 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: relcache.h,v 1.25 2001/06/29 21:08:25 tgl Exp $ + * $Id: relcache.h,v 1.26 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -33,6 +33,8 @@ extern void RelationClose(Relation relation); */ extern List *RelationGetIndexList(Relation relation); +extern void RelationInitIndexAccessInfo(Relation relation); + /* * Routines for backend startup */ @@ -61,6 +63,7 @@ extern void RelationPurgeLocalRelation(bool xactComitted); extern void RelationCacheAbort(void); +/* XLOG support */ extern void CreateDummyCaches(void); extern void DestroyDummyCaches(void); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index cb733d7970763edcaea8992ee2f073bb82f6394d..b59486860e4509b9b10f2c179d3df74f2688f2d7 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -33,7 +33,7 @@ * ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.22 2001/06/18 21:40:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.23 2001/10/06 23:21:44 tgl Exp $ * **********************************************************************/ @@ -171,18 +171,14 @@ static void plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname, * data structures such as fmgr info records therefore must live forever * as well. A better implementation would store all this stuff in a per- * function memory context that could be reclaimed at need. In the meantime, - * fmgr_info must be called in TopMemoryContext so that whatever it might - * allocate, and whatever the eventual function might allocate using fn_mcxt, - * will live forever too. + * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever + * it might allocate, and whatever the eventual function might allocate using + * fn_mcxt, will live forever too. */ static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo) { - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(functionId, finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(functionId, finfo, TopMemoryContext); } /********************************************************************** diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 2ab6632e336d6bb389b0797266c794de7aa17ea0..5c7e12ad19875196d6962f5718dea9289a0243be 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.33 2001/07/12 17:42:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.34 2001/10/06 23:21:44 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -92,18 +92,14 @@ PLpgSQL_function *plpgsql_curr_compile; * data structures such as fmgr info records therefore must live forever * as well. A better implementation would store all this stuff in a per- * function memory context that could be reclaimed at need. In the meantime, - * fmgr_info must be called in TopMemoryContext so that whatever it might - * allocate, and whatever the eventual function might allocate using fn_mcxt, - * will live forever too. + * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever + * it might allocate, and whatever the eventual function might allocate using + * fn_mcxt, will live forever too. */ static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo) { - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(functionId, finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(functionId, finfo, TopMemoryContext); } diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index cd3486fa6d6c6c9f8863b4ef1da3705765cf9825..8dcfb1c970c8497dacc812a78e8568b30f77da9a 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -29,7 +29,7 @@ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.7 2001/10/04 15:45:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.8 2001/10/06 23:21:45 tgl Exp $ * ********************************************************************* */ @@ -308,18 +308,14 @@ volatile int func_leave_calls = 0; * data structures such as fmgr info records therefore must live forever * as well. A better implementation would store all this stuff in a per- * function memory context that could be reclaimed at need. In the meantime, - * fmgr_info must be called in TopMemoryContext so that whatever it might - * allocate, and whatever the eventual function might allocate using fn_mcxt, - * will live forever too. + * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever + * it might allocate, and whatever the eventual function might allocate using + * fn_mcxt, will live forever too. */ static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo) { - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(functionId, finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(functionId, finfo, TopMemoryContext); } diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 29d6559821bd473e10011fa0e4fd24d0cc52baee..38d7d4345010ba80c42d76c6315d8cc79cfb56e2 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -31,7 +31,7 @@ * ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.42 2001/10/04 15:48:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.43 2001/10/06 23:21:45 tgl Exp $ * **********************************************************************/ @@ -187,18 +187,14 @@ static int pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp, * data structures such as fmgr info records therefore must live forever * as well. A better implementation would store all this stuff in a per- * function memory context that could be reclaimed at need. In the meantime, - * fmgr_info must be called in TopMemoryContext so that whatever it might - * allocate, and whatever the eventual function might allocate using fn_mcxt, - * will live forever too. + * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever + * it might allocate, and whatever the eventual function might allocate using + * fn_mcxt, will live forever too. */ static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo) { - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(functionId, finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(functionId, finfo, TopMemoryContext); } /**********************************************************************