diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index 56f13f9b8ba8000a076aef5e4b4bc05aefcdd4fa..ccb36b20c11b399daedc373f6b0be4a5e012a2e8 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.48 2001/03/22 06:16:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.49 2001/06/01 15:45:42 tgl Exp $
  *
  * NOTES
  *	  This cruft is the server side of PQfn.
@@ -58,15 +58,14 @@
  *
  *-------------------------------------------------------------------------
  */
-
 #include "postgres.h"
 
 #include "access/xact.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "tcop/fastpath.h"
+#include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 
@@ -114,78 +113,38 @@ SendFunctionResult(Datum retval,/* actual return value */
 }
 
 /*
- * This structure saves enough state so that one can avoid having to
- * do catalog lookups over and over again.	(Each RPC can require up
- * to FUNC_MAX_ARGS+2 lookups, which is quite tedious.)
- *
- * The previous incarnation of this code just assumed that any argument
- * of size <= 4 was by value; this is not correct.	There is no cheap
- * way to determine function argument length etc.; one must simply pay
- * the price of catalog lookups.
+ * Formerly, this code attempted to cache the function and type info
+ * looked up by fetch_fp_info, but only for the duration of a single
+ * transaction command (since in theory the info could change between
+ * commands).  This was utterly useless, because postgres.c executes
+ * each fastpath call as a separate transaction command, and so the
+ * cached data could never actually have been reused.  If it had worked
+ * as intended, it would have had problems anyway with dangling references
+ * in the FmgrInfo struct.  So, forget about caching and just repeat the
+ * syscache fetches on each usage.  They're not *that* expensive.
  */
 struct fp_info
 {
 	Oid			funcid;
 	FmgrInfo	flinfo;			/* function lookup info for funcid */
+	int16		arglen[FUNC_MAX_ARGS];
 	bool		argbyval[FUNC_MAX_ARGS];
-	int32		arglen[FUNC_MAX_ARGS];	/* signed (for varlena) */
+	int16		retlen;
 	bool		retbyval;
-	int32		retlen;			/* signed (for varlena) */
-	TransactionId xid;			/* when the lookup was done */
-	CommandId	cid;
 };
 
 /*
- * We implement one-back caching here.	If we need to do more, we can.
- * Most routines in tight loops (like PQfswrite -> F_LOWRITE) will do
- * the same thing repeatedly.
- */
-static struct fp_info last_fp = {InvalidOid};
-
-/*
- * valid_fp_info
- *
- * RETURNS:
- *		T if the state in 'fip' is valid for the given func OID
- *		F otherwise
- *
- * "invalid" means:
- * The saved state was either uninitialized, for another function,
- * or from a previous command.	(Commands can do updates, which
- * may invalidate catalog entries for subsequent commands.	This
- * is overly pessimistic but since there is no smarter invalidation
- * scheme...).
- */
-static bool
-valid_fp_info(Oid func_id, struct fp_info * fip)
-{
-	Assert(OidIsValid(func_id));
-	Assert(fip != (struct fp_info *) NULL);
-
-	return (OidIsValid(fip->funcid) &&
-			func_id == fip->funcid &&
-			TransactionIdIsCurrentTransactionId(fip->xid) &&
-			CommandIdIsCurrentCommandId(fip->cid));
-}
-
-/*
- * update_fp_info
+ * fetch_fp_info
  *
  * Performs catalog lookups to load a struct fp_info 'fip' for the
  * function 'func_id'.
- *
- * RETURNS:
- *		The correct information in 'fip'.  Sets 'fip->funcid' to
- *		InvalidOid if an exception occurs.
  */
 static void
-update_fp_info(Oid func_id, struct fp_info * fip)
+fetch_fp_info(Oid func_id, struct fp_info * fip)
 {
 	Oid		   *argtypes;		/* an oidvector */
 	Oid			rettype;
-	HeapTuple	func_htp,
-				type_htp;
-	Form_pg_type tp;
+	HeapTuple	func_htp;
 	Form_pg_proc pp;
 	int			i;
 
@@ -197,56 +156,32 @@ update_fp_info(Oid func_id, struct fp_info * fip)
 	 * funcid is OK, we clear the funcid here.	It must not be set to the
 	 * correct value until we are about to return with a good struct
 	 * fp_info, since we can be interrupted (i.e., with an elog(ERROR,
-	 * ...)) at any time.
+	 * ...)) at any time.  [No longer really an issue since we don't save
+	 * the struct fp_info across transactions anymore, but keep it anyway.]
 	 */
-	MemSet((char *) fip, 0, (int) sizeof(struct fp_info));
+	MemSet((char *) fip, 0, sizeof(struct fp_info));
 	fip->funcid = InvalidOid;
 
+	fmgr_info(func_id, &fip->flinfo);
+
 	func_htp = SearchSysCache(PROCOID,
 							  ObjectIdGetDatum(func_id),
 							  0, 0, 0);
 	if (!HeapTupleIsValid(func_htp))
-		elog(ERROR, "update_fp_info: cache lookup for function %u failed",
+		elog(ERROR, "fetch_fp_info: cache lookup for function %u failed",
 			 func_id);
 	pp = (Form_pg_proc) GETSTRUCT(func_htp);
 	rettype = pp->prorettype;
 	argtypes = pp->proargtypes;
 
-	fmgr_info(func_id, &fip->flinfo);
-
-	for (i = 0; i < fip->flinfo.fn_nargs; ++i)
+	for (i = 0; i < pp->pronargs; ++i)
 	{
 		if (OidIsValid(argtypes[i]))
-		{
-			type_htp = SearchSysCache(TYPEOID,
-									  ObjectIdGetDatum(argtypes[i]),
-									  0, 0, 0);
-			if (!HeapTupleIsValid(type_htp))
-				elog(ERROR, "update_fp_info: bad argument type %u for %u",
-					 argtypes[i], func_id);
-			tp = (Form_pg_type) GETSTRUCT(type_htp);
-			fip->argbyval[i] = tp->typbyval;
-			fip->arglen[i] = tp->typlen;
-			ReleaseSysCache(type_htp);
-		}						/* else it had better be VAR_LENGTH_ARG */
+			get_typlenbyval(argtypes[i], &fip->arglen[i], &fip->argbyval[i]);
 	}
 
 	if (OidIsValid(rettype))
-	{
-		type_htp = SearchSysCache(TYPEOID,
-								  ObjectIdGetDatum(rettype),
-								  0, 0, 0);
-		if (!HeapTupleIsValid(type_htp))
-			elog(ERROR, "update_fp_info: bad return type %u for %u",
-				 rettype, func_id);
-		tp = (Form_pg_type) GETSTRUCT(type_htp);
-		fip->retbyval = tp->typbyval;
-		fip->retlen = tp->typlen;
-		ReleaseSysCache(type_htp);
-	}							/* else it had better by VAR_LENGTH_RESULT */
-
-	fip->xid = GetCurrentTransactionId();
-	fip->cid = GetCurrentCommandId();
+		get_typlenbyval(rettype, &fip->retlen, &fip->retbyval);
 
 	ReleaseSysCache(func_htp);
 
@@ -286,6 +221,7 @@ HandleFunctionRequest(void)
 	Datum		retval;
 	int			i;
 	char	   *p;
+	struct fp_info my_fp;
 	struct fp_info *fip;
 
 	/*
@@ -324,14 +260,11 @@ HandleFunctionRequest(void)
 		return EOF;
 
 	/*
-	 * This is where the one-back caching is done. If you want to save
-	 * more state, make this a loop around an array.  Given the relatively
-	 * short lifespan of the cache, not clear that there's any win
-	 * possible.
+	 * There used to be a lame attempt at caching lookup info here.
+	 * Now we just do the lookups on every call.
 	 */
-	fip = &last_fp;
-	if (!valid_fp_info(fid, fip))
-		update_fp_info(fid, fip);
+	fip = &my_fp;
+	fetch_fp_info(fid, fip);
 
 	if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
 	{
diff --git a/src/include/tcop/fastpath.h b/src/include/tcop/fastpath.h
index 854e78b738e77398985c685efa116461aae48dbf..9c1e10e0179b7f8bd3b8026d81599f06a7b9eed5 100644
--- a/src/include/tcop/fastpath.h
+++ b/src/include/tcop/fastpath.h
@@ -3,29 +3,16 @@
  * fastpath.h
  *
  *
- *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fastpath.h,v 1.8 2001/01/24 19:43:28 momjian Exp $
- *
- * NOTES
- *	  This information pulled out of tcop/fastpath.c and put
- *	  here so that the PQfn() in be-pqexec.c could access it.
- *		-cim 2/26/91
+ * $Id: fastpath.h,v 1.9 2001/06/01 15:45:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef FASTPATH_H
 #define FASTPATH_H
 
-/* ----------------
- *		fastpath #defines
- * ----------------
- */
-#define VAR_LENGTH_RESULT		(-1)
-#define VAR_LENGTH_ARG			(-5)
-
 extern int	HandleFunctionRequest(void);
 
 #endif	 /* FASTPATH_H */