提交 0b370ea7 编写于 作者: T Tom Lane

Clean up some minor problems exposed by further thought about Panon's bug

report on old-style functions invoked by RI triggers.  We had a number of
other places that were being sloppy about which memory context FmgrInfo
subsidiary data will be allocated in.  Turns out none of them actually
cause a problem in 7.1, but this is for arcane reasons such as the fact
that old-style triggers aren't supported anyway.  To avoid getting burnt
later, I've restructured the trigger support so that we don't keep trigger
FmgrInfo structs in relcache memory.  Some other related cleanups too:
it's not really necessary to call fmgr_info at all while setting up
the index support info in relcache entries, because those ScanKeyEntry
structs are never used to invoke the functions.  This should speed up
relcache initialization a tiny bit.
上级 a1d9d096
......@@ -366,7 +366,6 @@ typedef struct Trigger
Oid tgoid;
char *tgname;
Oid tgfoid;
FmgrInfo tgfunc;
int16 tgtype;
bool tgenabled;
bool tgisconstraint;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.18 2001/01/24 19:42:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.19 2001/06/01 02:41:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -40,11 +40,13 @@ ScanKeyEntrySetIllegal(ScanKey entry)
entry->sk_flags = 0; /* just in case... */
entry->sk_attno = InvalidAttrNumber;
entry->sk_procedure = 0; /* should be InvalidRegProcedure */
entry->sk_func.fn_oid = InvalidOid;
entry->sk_argument = (Datum) 0;
}
/*
* ScanKeyEntryInitialize
* Initializes an scan key entry.
* Initializes a scan key entry.
*
* Note:
* Assumes the scan key entry is valid.
......@@ -64,7 +66,6 @@ ScanKeyEntryInitialize(ScanKey entry,
entry->sk_procedure = procedure;
entry->sk_argument = argument;
fmgr_info(procedure, &entry->sk_func);
entry->sk_nargs = entry->sk_func.fn_nargs;
Assert(ScanKeyEntryIsLegal(entry));
}
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.49 2001/05/31 18:16:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.50 2001/06/01 02:41:35 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relationId
......@@ -232,7 +232,7 @@ index_beginscan(Relation relation,
uint16 numberOfKeys,
ScanKey key)
{
IndexScanDesc scandesc;
IndexScanDesc scan;
RegProcedure procedure;
RELATION_CHECKS;
......@@ -249,14 +249,22 @@ index_beginscan(Relation relation,
*/
LockRelation(relation, AccessShareLock);
scandesc = (IndexScanDesc)
scan = (IndexScanDesc)
DatumGetPointer(OidFunctionCall4(procedure,
PointerGetDatum(relation),
BoolGetDatum(scanFromEnd),
UInt16GetDatum(numberOfKeys),
PointerGetDatum(key)));
return scandesc;
/*
* We want to look up the amgettuple procedure just once per scan,
* not once per index_getnext call. So do it here and save
* the fmgr info result in the scan descriptor.
*/
GET_SCAN_PROCEDURE(beginscan, amgettuple);
fmgr_info(procedure, &scan->fn_getnext);
return scan;
}
/* ----------------
......@@ -345,19 +353,9 @@ index_getnext(IndexScanDesc scan,
SCAN_CHECKS;
/*
* Look up the access procedure only once per scan.
*/
if (scan->fn_getnext.fn_oid == InvalidOid)
{
RegProcedure procedure;
GET_SCAN_PROCEDURE(getnext, amgettuple);
fmgr_info(procedure, &scan->fn_getnext);
}
/*
* have the am's gettuple proc do all the work.
* index_beginscan already set up fn_getnext.
*/
result = (RetrieveIndexResult)
DatumGetPointer(FunctionCall2(&scan->fn_getnext,
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.50 2001/05/30 19:53:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.51 2001/06/01 02:41:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -458,6 +458,8 @@ RelationInvokeStrategy(Relation relation,
/* ----------------
* OperatorRelationFillScanKeyEntry
*
* Initialize a ScanKey entry given already-opened pg_operator relation.
* ----------------
*/
static void
......@@ -498,6 +500,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
operatorObjectId);
}
MemSet(entry, 0, sizeof(*entry));
entry->sk_flags = 0;
entry->sk_procedure = ((Form_pg_operator) GETSTRUCT(tuple))->oprcode;
......@@ -511,14 +514,29 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
"OperatorRelationFillScanKeyEntry: no procedure for operator %u",
operatorObjectId);
fmgr_info(entry->sk_procedure, &entry->sk_func);
entry->sk_nargs = entry->sk_func.fn_nargs;
/*
* 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!)
*/
}
/*
* IndexSupportInitialize
* Initializes an index strategy and associated support procedures.
*
* Data is returned into *indexStrategy, *indexSupport, and *isUnique,
* all of which are objects allocated by the caller.
*
* The primary input keys are indexObjectId and accessMethodObjectId.
* The caller also passes maxStrategyNumber, maxSupportNumber, and
* maxAttributeNumber, since these indicate the size of the indexStrategy
* and indexSupport arrays it has allocated --- but in practice these
* numbers must always match those obtainable from the system catalog
* entries for the index and access method.
*/
void
IndexSupportInitialize(IndexStrategy indexStrategy,
......@@ -578,7 +596,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
if (!OidIsValid(iform->indkey[attIndex]))
{
if (attIndex == InvalidAttrNumber)
elog(ERROR, "IndexSupportInitialize: no pg_index tuple");
elog(ERROR, "IndexSupportInitialize: bogus pg_index tuple");
break;
}
......@@ -637,6 +655,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
heap_close(relation, AccessShareLock);
}
/* Now load the strategy information for the index operators */
ScanKeyEntryInitialize(&entry[0], 0,
Anum_pg_amop_amopid,
F_OIDEQ,
......@@ -644,7 +663,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
ScanKeyEntryInitialize(&entry[1], 0,
Anum_pg_amop_amopclaid,
F_OIDEQ, 0);
F_OIDEQ,
0); /* will fill below */
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
operatorRelation = heap_openr(OperatorRelationName, AccessShareLock);
......@@ -670,9 +690,11 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
Form_pg_amop aform;
aform = (Form_pg_amop) GETSTRUCT(tuple);
strategy = aform->amopstrategy;
Assert(strategy > 0 && strategy <= maxStrategyNumber);
OperatorRelationFillScanKeyEntry(operatorRelation,
aform->amopopr,
StrategyMapGetScanKeyEntry(map, aform->amopstrategy));
StrategyMapGetScanKeyEntry(map, strategy));
}
heap_endscan(scan);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.152 2001/05/30 20:52:32 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.153 2001/06/01 02:41:35 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -722,6 +722,9 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
/* ----------------------------------------------------------------
* InitIndexStrategy
*
* XXX this is essentially the same as relcache.c's
* IndexedAccessMethodInitialize(), and probably ought to be merged with it.
* ----------------------------------------------------------------
*/
void
......@@ -733,18 +736,16 @@ InitIndexStrategy(int numatts,
RegProcedure *support;
uint16 amstrategies;
uint16 amsupport;
Oid attrelid;
Size strsize;
/*
* get information from the index relation descriptor
*/
attrelid = indexRelation->rd_att->attrs[0]->attrelid;
amstrategies = indexRelation->rd_am->amstrategies;
amsupport = indexRelation->rd_am->amsupport;
/*
* get the size of the strategy
* compute the size of the strategy array
*/
strsize = AttributeNumberGetIndexStrategySize(numatts, amstrategies);
......@@ -779,7 +780,8 @@ InitIndexStrategy(int numatts,
IndexSupportInitialize(strategy, support,
&indexRelation->rd_uniqueindex,
attrelid, accessMethodObjectId,
RelationGetRelid(indexRelation),
accessMethodObjectId,
amstrategies, amsupport, numatts);
/*
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.58 2001/05/20 20:28:17 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.59 2001/06/01 02:41:35 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
......@@ -71,12 +71,13 @@ static void OperatorUpd(Oid baseId, Oid commId, Oid negId);
*
* performs a scan on pg_operator for an operator tuple
* with given name and left/right type oids.
* ----------------------------------------------------------------
*
* pg_operator_desc -- reldesc for pg_operator
* operatorName -- name of operator to fetch
* leftObjectId -- left data type oid of operator to fetch
* rightObjectId -- right data type oid of operator to fetch
* defined -- set TRUE if defined (not a shell)
* ----------------------------------------------------------------
*/
static Oid
OperatorGetWithOpenRelation(Relation pg_operator_desc,
......@@ -88,26 +89,23 @@ OperatorGetWithOpenRelation(Relation pg_operator_desc,
HeapScanDesc pg_operator_scan;
Oid operatorObjectId;
HeapTuple tup;
static ScanKeyData opKey[3] = {
{0, Anum_pg_operator_oprname, F_NAMEEQ},
{0, Anum_pg_operator_oprleft, F_OIDEQ},
{0, Anum_pg_operator_oprright, F_OIDEQ},
};
fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
fmgr_info(F_OIDEQ, &opKey[1].sk_func);
fmgr_info(F_OIDEQ, &opKey[2].sk_func);
opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
ScanKeyData opKey[3];
/*
* form scan key
*/
opKey[0].sk_argument = PointerGetDatum(operatorName);
opKey[1].sk_argument = ObjectIdGetDatum(leftObjectId);
opKey[2].sk_argument = ObjectIdGetDatum(rightObjectId);
ScanKeyEntryInitialize(&opKey[0], 0x0,
Anum_pg_operator_oprname,
F_NAMEEQ,
PointerGetDatum(operatorName));
ScanKeyEntryInitialize(&opKey[1], 0x0,
Anum_pg_operator_oprleft,
F_OIDEQ,
ObjectIdGetDatum(leftObjectId));
ScanKeyEntryInitialize(&opKey[2], 0x0,
Anum_pg_operator_oprright,
F_OIDEQ,
ObjectIdGetDatum(rightObjectId));
/*
* begin the scan
......@@ -451,7 +449,6 @@ OperatorDef(char *operatorName,
int i,
j;
Relation pg_operator_desc;
HeapScanDesc pg_operator_scan;
HeapTuple tup;
char nulls[Natts_pg_operator];
......@@ -471,19 +468,7 @@ OperatorDef(char *operatorName,
int nargs;
NameData oname;
TupleDesc tupDesc;
static ScanKeyData opKey[3] = {
{0, Anum_pg_operator_oprname, F_NAMEEQ},
{0, Anum_pg_operator_oprleft, F_OIDEQ},
{0, Anum_pg_operator_oprright, F_OIDEQ},
};
fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
fmgr_info(F_OIDEQ, &opKey[1].sk_func);
fmgr_info(F_OIDEQ, &opKey[2].sk_func);
opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
ScanKeyData opKey[3];
operatorObjectId = OperatorGet(operatorName,
leftTypeName,
......@@ -753,13 +738,22 @@ OperatorDef(char *operatorName,
*/
if (operatorObjectId)
{
opKey[0].sk_argument = PointerGetDatum(operatorName);
opKey[1].sk_argument = ObjectIdGetDatum(leftTypeId);
opKey[2].sk_argument = ObjectIdGetDatum(rightTypeId);
/* Make sure we can see the shell even if it is new in current cmd */
CommandCounterIncrement();
ScanKeyEntryInitialize(&opKey[0], 0x0,
Anum_pg_operator_oprname,
F_NAMEEQ,
PointerGetDatum(operatorName));
ScanKeyEntryInitialize(&opKey[1], 0x0,
Anum_pg_operator_oprleft,
F_OIDEQ,
ObjectIdGetDatum(leftTypeId));
ScanKeyEntryInitialize(&opKey[2], 0x0,
Anum_pg_operator_oprright,
F_OIDEQ,
ObjectIdGetDatum(rightTypeId));
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
SnapshotSelf, /* no cache? */
......@@ -789,7 +783,6 @@ OperatorDef(char *operatorName,
heap_insert(pg_operator_desc, tup);
operatorObjectId = tup->t_data->t_oid;
}
if (RelationGetForm(pg_operator_desc)->relhasindex)
......@@ -841,17 +834,11 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
char nulls[Natts_pg_operator];
char replaces[Natts_pg_operator];
Datum values[Natts_pg_operator];
static ScanKeyData opKey[1] = {
{0, ObjectIdAttributeNumber, F_OIDEQ},
};
fmgr_info(F_OIDEQ, &opKey[0].sk_func);
opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
ScanKeyData opKey[1];
for (i = 0; i < Natts_pg_operator; ++i)
{
values[i] = (Datum) NULL;
values[i] = (Datum) 0;
replaces[i] = ' ';
nulls[i] = ' ';
}
......@@ -865,7 +852,10 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
*/
CommandCounterIncrement();
opKey[0].sk_argument = ObjectIdGetDatum(commId);
ScanKeyEntryInitialize(&opKey[0], 0x0,
ObjectIdAttributeNumber,
F_OIDEQ,
ObjectIdGetDatum(commId));
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
......@@ -993,7 +983,6 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc, RowExclusiveLock);
}
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.137 2001/05/27 09:59:29 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.138 2001/06/01 02:41:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -636,6 +636,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
resultRelInfo = makeNode(ResultRelInfo);
resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
resultRelInfo->ri_RelationDesc = rel;
resultRelInfo->ri_TrigDesc = rel->trigdesc;
ExecOpenIndices(resultRelInfo);
......@@ -868,12 +869,12 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
skip_tuple = false;
/* BEFORE ROW INSERT Triggers */
if (rel->trigdesc &&
rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
{
HeapTuple newtuple;
newtuple = ExecBRInsertTriggers(estate, rel, tuple);
newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
if (newtuple == NULL) /* "do nothing" */
skip_tuple = true;
......@@ -903,8 +904,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
/* AFTER ROW INSERT Triggers */
if (rel->trigdesc)
ExecARInsertTriggers(estate, rel, tuple);
if (resultRelInfo->ri_TrigDesc)
ExecARInsertTriggers(estate, resultRelInfo, tuple);
}
for (i = 0; i < attr_count; i++)
......
此差异已折叠。
......@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.142 2001/05/27 20:48:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.143 2001/06/01 02:41:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -830,6 +830,8 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_NumIndices = 0;
resultRelInfo->ri_IndexRelationDescs = NULL;
resultRelInfo->ri_IndexRelationInfo = NULL;
resultRelInfo->ri_TrigDesc = resultRelationDesc->trigdesc;
resultRelInfo->ri_TrigFunctions = NULL;
resultRelInfo->ri_ConstraintExprs = NULL;
resultRelInfo->ri_junkFilter = NULL;
......@@ -1232,12 +1234,12 @@ ExecAppend(TupleTableSlot *slot,
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW INSERT Triggers */
if (resultRelationDesc->trigdesc &&
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
{
HeapTuple newtuple;
newtuple = ExecBRInsertTriggers(estate, resultRelationDesc, tuple);
newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
if (newtuple == NULL) /* "do nothing" */
return;
......@@ -1283,8 +1285,8 @@ ExecAppend(TupleTableSlot *slot,
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
/* AFTER ROW INSERT Triggers */
if (resultRelationDesc->trigdesc)
ExecARInsertTriggers(estate, resultRelationDesc, tuple);
if (resultRelInfo->ri_TrigDesc)
ExecARInsertTriggers(estate, resultRelInfo, tuple);
}
/* ----------------------------------------------------------------
......@@ -1311,12 +1313,12 @@ ExecDelete(TupleTableSlot *slot,
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW DELETE Triggers */
if (resultRelationDesc->trigdesc &&
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
{
bool dodelete;
dodelete = ExecBRDeleteTriggers(estate, tupleid);
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
if (!dodelete) /* "do nothing" */
return;
......@@ -1370,8 +1372,8 @@ ldelete:;
*/
/* AFTER ROW DELETE Triggers */
if (resultRelationDesc->trigdesc)
ExecARDeleteTriggers(estate, tupleid);
if (resultRelInfo->ri_TrigDesc)
ExecARDeleteTriggers(estate, resultRelInfo, tupleid);
}
/* ----------------------------------------------------------------
......@@ -1418,12 +1420,13 @@ ExecReplace(TupleTableSlot *slot,
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW UPDATE Triggers */
if (resultRelationDesc->trigdesc &&
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
{
HeapTuple newtuple;
newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
tupleid, tuple);
if (newtuple == NULL) /* "do nothing" */
return;
......@@ -1519,8 +1522,8 @@ lreplace:;
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
/* AFTER ROW UPDATE Triggers */
if (resultRelationDesc->trigdesc)
ExecARUpdateTriggers(estate, tupleid, tuple);
if (resultRelInfo->ri_TrigDesc)
ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple);
}
static char *
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.77 2001/03/22 03:59:55 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.78 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -205,7 +205,6 @@ CatalogCacheInitializeCache(CatCache *cache)
/*
* switch to the cache context so our allocations do not vanish at the
* end of a transaction
*
*/
if (!CacheMemoryContext)
CreateCacheMemoryContext();
......@@ -214,13 +213,11 @@ CatalogCacheInitializeCache(CatCache *cache)
/*
* copy the relcache's tuple descriptor to permanent cache storage
*
*/
tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
/*
* return to the caller's memory context and close the rel
*
*/
MemoryContextSwitchTo(oldcxt);
......@@ -231,7 +228,6 @@ CatalogCacheInitializeCache(CatCache *cache)
/*
* initialize cache's key information
*
*/
for (i = 0; i < cache->cc_nkeys; ++i)
{
......@@ -255,9 +251,23 @@ 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_nargs = cache->cc_skey[i].sk_func.fn_nargs;
cache->cc_skey[i].sk_func.fn_mcxt = CacheMemoryContext;
/* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
cache->cc_skey[i].sk_attno = cache->cc_key[i];
......@@ -270,7 +280,6 @@ CatalogCacheInitializeCache(CatCache *cache)
/*
* mark this cache fully initialized
*
*/
cache->cc_tupdesc = tupdesc;
}
......@@ -705,7 +714,6 @@ InitCatCache(int id,
* certain system indexes that support critical syscaches.
* We can't use an indexscan to fetch these, else we'll get into
* infinite recursion. A plain heap scan will work, however.
*
*/
static bool
IndexScanOK(CatCache *cache, ScanKey cur_skey)
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.135 2001/05/30 14:15:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.136 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1161,19 +1161,20 @@ IndexedAccessMethodInitialize(Relation relation)
int natts;
Size stratSize;
Size supportSize;
uint16 relamstrategies;
uint16 relamsupport;
uint16 amstrategies;
uint16 amsupport;
natts = relation->rd_rel->relnatts;
relamstrategies = relation->rd_am->amstrategies;
stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies);
amstrategies = relation->rd_am->amstrategies;
amsupport = relation->rd_am->amsupport;
stratSize = AttributeNumberGetIndexStrategySize(natts, amstrategies);
strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext,
stratSize);
relamsupport = relation->rd_am->amsupport;
if (relamsupport > 0)
if (amsupport > 0)
{
supportSize = natts * (relamsupport * sizeof(RegProcedure));
supportSize = natts * (amsupport * sizeof(RegProcedure));
support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext,
supportSize);
}
......@@ -1182,9 +1183,9 @@ IndexedAccessMethodInitialize(Relation relation)
IndexSupportInitialize(strategy, support,
&relation->rd_uniqueindex,
relation->rd_att->attrs[0]->attrelid,
RelationGetRelid(relation),
relation->rd_rel->relam,
relamstrategies, relamsupport, natts);
amstrategies, amsupport, natts);
RelationSetIndexSupport(relation, strategy, support);
}
......@@ -1212,26 +1213,22 @@ formrdesc(char *relationName,
/*
* allocate new relation desc
*
*/
relation = (Relation) palloc(sizeof(RelationData));
MemSet((char *) relation, 0, sizeof(RelationData));
/*
* don't open the unix file yet..
*
*/
relation->rd_fd = -1;
/*
* initialize reference count
*
*/
RelationSetReferenceCount(relation, 1);
/*
* all entries built with this routine are nailed-in-cache
*
*/
relation->rd_isnailed = true;
......@@ -1241,7 +1238,6 @@ formrdesc(char *relationName,
* The data we insert here is pretty incomplete/bogus, but it'll serve to
* get us launched. RelationCacheInitializePhase2() will read the
* real data from pg_class and replace what we've done here.
*
*/
relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE);
......@@ -1266,13 +1262,11 @@ formrdesc(char *relationName,
/*
* initialize attribute tuple form
*
*/
relation->rd_att = CreateTemplateTupleDesc(natts);
/*
* initialize tuple desc info
*
*/
for (i = 0; i < natts; i++)
{
......@@ -1283,14 +1277,12 @@ formrdesc(char *relationName,
}
/*
* initialize relation id
*
* initialize relation id from info in att array (my, this is ugly)
*/
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
/*
* initialize the relation's lock manager and RelFileNode information
*
*/
RelationInitLockInfo(relation); /* see lmgr.c */
......@@ -1303,7 +1295,6 @@ formrdesc(char *relationName,
/*
* initialize the rel-has-index flag, using hardwired knowledge
*
*/
relation->rd_rel->relhasindex = false;
......@@ -1322,7 +1313,6 @@ formrdesc(char *relationName,
/*
* add new reldesc to relcache
*
*/
RelationCacheInsert(relation);
}
......@@ -2755,10 +2745,8 @@ init_irels(void)
{
fmgr_info(SMD(i).sk_procedure,
&(SMD(i).sk_func));
SMD(i).sk_nargs = SMD(i).sk_func.fn_nargs;
}
/*
* use a real field called rd_istrat instead of the bogosity of
* hanging invisible fields off the end of a structure - jolly
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.52 2001/05/19 09:28:08 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.53 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -114,6 +114,15 @@ fmgr_lookupByName(const char *name)
/*
* This routine fills a FmgrInfo struct, given the OID
* of the function to be called.
*
* The caller's CurrentMemoryContext is used as the fn_mcxt of the info
* struct; this means that any subsidiary data attached to the info struct
* (either by fmgr_info itself, or later on by a function call handler)
* 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.
*/
void
fmgr_info(Oid functionId, FmgrInfo *finfo)
......@@ -124,8 +133,9 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
char *prosrc;
/*
* fn_oid *must* be filled in last. Code may assume that is fn_oid is valid,
* the whole struct is valid. Some FmgrInfo struct's do survive elogs.
* fn_oid *must* be filled in last. Some code assumes that if fn_oid is
* valid, the whole struct is valid. Some FmgrInfo struct's do survive
* elogs.
*/
finfo->fn_oid = InvalidOid;
finfo->fn_extra = NULL;
......@@ -133,10 +143,8 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
{
/*
* Fast path for builtin functions: don't bother consulting
* pg_proc
* Fast path for builtin functions: don't bother consulting pg_proc
*/
finfo->fn_nargs = fbp->nargs;
finfo->fn_strict = fbp->strict;
......@@ -171,7 +179,6 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
switch (procedureStruct->prolang)
{
case INTERNALlanguageId:
/*
* For an ordinary builtin function, we should never get here
* because the isbuiltin() search above will have succeeded.
......
......@@ -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.14 2001/01/24 19:43:19 momjian Exp $
* $Id: skey.h,v 1.15 2001/06/01 02:41:36 tgl Exp $
*
*
* Note:
......@@ -25,18 +25,18 @@ typedef struct ScanKeyData
bits16 sk_flags; /* flags */
AttrNumber sk_attno; /* domain number */
RegProcedure sk_procedure; /* procedure OID */
FmgrInfo sk_func;
int32 sk_nargs;
FmgrInfo sk_func; /* fmgr call info for procedure */
Datum sk_argument; /* data to compare */
} ScanKeyData;
typedef ScanKeyData *ScanKey;
/* ScanKeyData flags */
#define SK_ISNULL 0x1 /* sk_argument is NULL */
#define SK_UNARY 0x2 /* unary function (currently unsupported) */
#define SK_NEGATE 0x4 /* negate function result */
#define SK_COMMUTE 0x8 /* commute function (not fully supported) */
#define SK_ISNULL 0x1
#define SK_UNARY 0x2
#define SK_NEGATE 0x4
#define SK_COMMUTE 0x8
#define ScanUnmarked 0x01
#define ScanUncheckedPrevious 0x02
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: trigger.h,v 1.26 2001/03/22 04:00:43 momjian Exp $
* $Id: trigger.h,v 1.27 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -90,15 +90,25 @@ extern void FreeTriggerDesc(TriggerDesc *trigdesc);
extern bool equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2);
extern HeapTuple ExecBRInsertTriggers(EState *estate,
Relation rel, HeapTuple tuple);
ResultRelInfo *relinfo,
HeapTuple trigtuple);
extern void ExecARInsertTriggers(EState *estate,
Relation rel, HeapTuple tuple);
extern bool ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid);
extern void ExecARDeleteTriggers(EState *estate, ItemPointer tupleid);
extern HeapTuple ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid,
HeapTuple tuple);
extern void ExecARUpdateTriggers(EState *estate, ItemPointer tupleid,
HeapTuple tuple);
ResultRelInfo *relinfo,
HeapTuple trigtuple);
extern bool ExecBRDeleteTriggers(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tupleid);
extern void ExecARDeleteTriggers(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tupleid);
extern HeapTuple ExecBRUpdateTriggers(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tupleid,
HeapTuple newtuple);
extern void ExecARUpdateTriggers(EState *estate,
ResultRelInfo *relinfo,
ItemPointer tupleid,
HeapTuple newtuple);
/* ----------
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: execnodes.h,v 1.60 2001/05/27 20:48:51 tgl Exp $
* $Id: execnodes.h,v 1.61 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -198,16 +198,18 @@ typedef struct JunkFilter
/* ----------------
* ResultRelInfo information
*
* whenever we update an existing relation, we have to
* update indices on the relation. The ResultRelInfo class
* is used to hold all the information on result relations,
* including indices.. -cim 10/15/89
* Whenever we update an existing relation, we have to
* update indices on the relation, and perhaps also fire triggers.
* The ResultRelInfo class is used to hold all the information needed
* about a result relation, including indices.. -cim 10/15/89
*
* RangeTableIndex result relation's range table index
* RelationDesc relation descriptor for result relation
* NumIndices # of indices existing on result relation
* IndexRelationDescs array of relation descriptors for indices
* IndexRelationInfo array of key/attr info for indices
* TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions
* ConstraintExprs array of constraint-checking expressions
* junkFilter for removing junk attributes from tuples
* ----------------
......@@ -220,6 +222,8 @@ typedef struct ResultRelInfo
int ri_NumIndices;
RelationPtr ri_IndexRelationDescs;
IndexInfo **ri_IndexRelationInfo;
TriggerDesc *ri_TrigDesc;
FmgrInfo *ri_TrigFunctions;
List **ri_ConstraintExprs;
JunkFilter *ri_junkFilter;
} ResultRelInfo;
......
......@@ -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.45 2001/03/22 04:01:14 momjian Exp $
* $Id: rel.h,v 1.46 2001/06/01 02:41:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -47,13 +47,11 @@ typedef LockInfoData *LockInfo;
* Likewise, this struct really belongs to trigger.h, but for convenience
* we put it here.
*/
typedef struct Trigger
{
Oid tgoid;
char *tgname;
Oid tgfoid;
FmgrInfo tgfunc;
int16 tgtype;
bool tgenabled;
bool tgisconstraint;
......@@ -66,16 +64,23 @@ typedef struct Trigger
typedef struct TriggerDesc
{
/* index data to identify which triggers are which */
uint16 n_before_statement[4];
uint16 n_before_row[4];
uint16 n_after_row[4];
uint16 n_after_statement[4];
Trigger **tg_before_statement[4];
Trigger **tg_before_row[4];
Trigger **tg_after_row[4];
Trigger **tg_after_statement[4];
/* the actual array of triggers is here */
/*
* Index data to identify which triggers are which. Since each trigger
* can appear in more than one class, for each class we provide a list
* of integer indexes into the triggers array.
*/
#define TRIGGER_NUM_EVENT_CLASSES 4
uint16 n_before_statement[TRIGGER_NUM_EVENT_CLASSES];
uint16 n_before_row[TRIGGER_NUM_EVENT_CLASSES];
uint16 n_after_row[TRIGGER_NUM_EVENT_CLASSES];
uint16 n_after_statement[TRIGGER_NUM_EVENT_CLASSES];
int *tg_before_statement[TRIGGER_NUM_EVENT_CLASSES];
int *tg_before_row[TRIGGER_NUM_EVENT_CLASSES];
int *tg_after_row[TRIGGER_NUM_EVENT_CLASSES];
int *tg_after_statement[TRIGGER_NUM_EVENT_CLASSES];
/* The actual array of triggers is here */
Trigger *triggers;
int numtriggers;
} TriggerDesc;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册