diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-31 17:32:33 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-31 17:32:33 +0000 |
commit | e1107fc28536bf5f24f388bd701bffb98c09cd06 (patch) | |
tree | cfcec30a9baf6d02f130347a97f0bb3bbde75631 /src | |
parent | c9a001a11e82bce3d8e9ff7706bc19cb39a16b1b (diff) | |
download | postgresql-e1107fc28536bf5f24f388bd701bffb98c09cd06.tar.gz postgresql-e1107fc28536bf5f24f388bd701bffb98c09cd06.zip |
RI triggers would fail for datatypes using old-style equal function,
because cached fmgr info contained reference to a shorter-lived data
structure. Also guard against possibility that fmgr_info could fail,
leaving an incomplete entry present in the hash table.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 71c1ccd4549..dc5f7c8495d 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.24 2001/05/07 19:57:24 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.25 2001/05/31 17:32:33 tgl Exp $ * * ---------- */ @@ -3243,7 +3243,9 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) if (!found) { HeapTuple opr_tup; - Form_pg_operator opr_struct; + Oid opr_proc; + MemoryContext oldcontext; + FmgrInfo finfo; opr_tup = SearchSysCache(OPERNAME, PointerGetDatum("="), @@ -3251,9 +3253,22 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) ObjectIdGetDatum(typeid), CharGetDatum('b')); if (!HeapTupleIsValid(opr_tup)) - elog(ERROR, "ri_AttributesEqual(): cannot find '=' operator " - "for type %u", typeid); - opr_struct = (Form_pg_operator) GETSTRUCT(opr_tup); + elog(ERROR, + "ri_AttributesEqual(): cannot find '=' operator for type %u", + typeid); + opr_proc = ((Form_pg_operator) GETSTRUCT(opr_tup))->oprcode; + ReleaseSysCache(opr_tup); + + /* + * Since fmgr_info could fail, call it *before* creating the + * hashtable entry --- otherwise we could elog leaving an incomplete + * entry in the hashtable. Also, because this will be a permanent + * 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); entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache, (char *) &typeid, @@ -3263,8 +3278,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) elog(FATAL, "can't insert into RI operator cache"); entry->typeid = typeid; - fmgr_info(opr_struct->oprcode, &(entry->oprfmgrinfo)); - ReleaseSysCache(opr_tup); + memcpy(&(entry->oprfmgrinfo), &finfo, sizeof(FmgrInfo)); } /* |