]> granicus.if.org Git - postgresql/commitdiff
RI triggers would fail for datatypes using old-style equal function,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 May 2001 17:32:33 +0000 (17:32 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 May 2001 17:32:33 +0000 (17:32 +0000)
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.

src/backend/utils/adt/ri_triggers.c

index 71c1ccd4549a9259fc46408897908df785adc187..dc5f7c8495d44a6dfe9903a47b7039a609f0c910 100644 (file)
@@ -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));
        }
 
        /*