Make sure fmgr_info() fills in fn_oid last, so that no partially
authorPeter Eisentraut
Sat, 19 May 2001 09:28:08 +0000 (09:28 +0000)
committerPeter Eisentraut
Sat, 19 May 2001 09:28:08 +0000 (09:28 +0000)
initialized FmgrInfo structs linger after elog.

src/backend/utils/fmgr/fmgr.c

index 08c35327d0282b3c7195c0852407f021330ab958..090807129f50c49c26398b65b77d36f3b17b1dab 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.51 2001/03/22 03:59:59 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.52 2001/05/19 09:28:08 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,8 +57,8 @@ typedef struct
 } Oldstyle_fnextra;
 
 
-static void fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
-static void fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
+static void fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
+static void fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
 static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
 static Datum fmgr_untrusted(PG_FUNCTION_ARGS);
 
@@ -123,7 +123,11 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
    Form_pg_proc procedureStruct;
    char       *prosrc;
 
-   finfo->fn_oid = functionId;
+   /*
+    * 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.
+    */
+   finfo->fn_oid = InvalidOid;
    finfo->fn_extra = NULL;
    finfo->fn_mcxt = CurrentMemoryContext;
 
@@ -138,6 +142,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
        finfo->fn_strict = fbp->strict;
        finfo->fn_retset = fbp->retset;
        finfo->fn_addr = fbp->func;
+       finfo->fn_oid = functionId;
        return;
    }
 
@@ -158,6 +163,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
    {
        /* This isn't really supported anymore... */
        finfo->fn_addr = fmgr_untrusted;
+       finfo->fn_oid = functionId;
        ReleaseSysCache(procedureTuple);
        return;
    }
@@ -187,7 +193,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
            break;
 
        case ClanguageId:
-           fmgr_info_C_lang(finfo, procedureTuple);
+           fmgr_info_C_lang(functionId, finfo, procedureTuple);
            break;
 
        case SQLlanguageId:
@@ -195,18 +201,20 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
            break;
 
        default:
-           fmgr_info_other_lang(finfo, procedureTuple);
+           fmgr_info_other_lang(functionId, finfo, procedureTuple);
            break;
    }
 
+   finfo->fn_oid = functionId;
    ReleaseSysCache(procedureTuple);
 }
 
 /*
- * Special fmgr_info processing for C-language functions
+ * Special fmgr_info processing for C-language functions.  Note that
+ * finfo->fn_oid is not valid yet.
  */
 static void
-fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
+fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 {
    Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
    Datum       prosrcattr,
@@ -224,14 +232,14 @@ fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
                                 Anum_pg_proc_prosrc, &isnull);
    if (isnull)
        elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
-            finfo->fn_oid);
+            functionId);
    prosrcstring = DatumGetCString(DirectFunctionCall1(textout, prosrcattr));
 
    probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
                                 Anum_pg_proc_probin, &isnull);
    if (isnull)
        elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
-            finfo->fn_oid);
+            functionId);
    probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr));
 
    /* Look up the function itself */
@@ -276,10 +284,11 @@ fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
 }
 
 /*
- * Special fmgr_info processing for other-language functions
+ * Special fmgr_info processing for other-language functions.  Note
+ * that finfo->fn_oid is not valid yet.
  */
 static void
-fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
+fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 {
    Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
    Oid         language = procedureStruct->prolang;
@@ -312,7 +321,7 @@ fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
    else
    {
        elog(ERROR, "fmgr_info: function %u: unsupported language %u",
-            finfo->fn_oid, language);
+            functionId, language);
    }
    ReleaseSysCache(languageTuple);
 }