mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 11:02:12 +03:00
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.
This commit is contained in:
parent
c9a001a11e
commit
e1107fc285
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user