Commit e1107fc2 authored by Tom Lane's avatar Tom Lane

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.
parent c9a001a1
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group * Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
* Copyright 1999 Jan Wieck * 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) ...@@ -3243,7 +3243,9 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
if (!found) if (!found)
{ {
HeapTuple opr_tup; HeapTuple opr_tup;
Form_pg_operator opr_struct; Oid opr_proc;
MemoryContext oldcontext;
FmgrInfo finfo;
opr_tup = SearchSysCache(OPERNAME, opr_tup = SearchSysCache(OPERNAME,
PointerGetDatum("="), PointerGetDatum("="),
...@@ -3251,9 +3253,22 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) ...@@ -3251,9 +3253,22 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
ObjectIdGetDatum(typeid), ObjectIdGetDatum(typeid),
CharGetDatum('b')); CharGetDatum('b'));
if (!HeapTupleIsValid(opr_tup)) if (!HeapTupleIsValid(opr_tup))
elog(ERROR, "ri_AttributesEqual(): cannot find '=' operator " elog(ERROR,
"for type %u", typeid); "ri_AttributesEqual(): cannot find '=' operator for type %u",
opr_struct = (Form_pg_operator) GETSTRUCT(opr_tup); 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, entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
(char *) &typeid, (char *) &typeid,
...@@ -3263,8 +3278,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) ...@@ -3263,8 +3278,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
elog(FATAL, "can't insert into RI operator cache"); elog(FATAL, "can't insert into RI operator cache");
entry->typeid = typeid; entry->typeid = typeid;
fmgr_info(opr_struct->oprcode, &(entry->oprfmgrinfo)); memcpy(&(entry->oprfmgrinfo), &finfo, sizeof(FmgrInfo));
ReleaseSysCache(opr_tup);
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment