diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 4d46013d7d..2bc2fc4c83 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -418,7 +418,7 @@ interpret_function_parameter_list(ParseState *pstate,
 			have_names = true;
 		}
 
-		if (inParameterNames_list)
+		if (isinput && inParameterNames_list)
 			*inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
 
 		if (fp->defexpr)
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 8f6a46fa61..f6d6b3d428 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3572,6 +3572,24 @@ print_function_sqlbody(StringInfo buf, HeapTuple proctup)
 	dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
 	numargs = get_func_arg_info(proctup,
 								&argtypes, &argnames, &argmodes);
+
+	/*
+	 * Param IDs count input parameters only, so remove the names of output
+	 * parameters to keep the array indexable by paramid.
+	 */
+	if (argnames && argmodes)
+	{
+		int			ninput = 0;
+
+		for (int i = 0; i < numargs; i++)
+		{
+			if (argmodes[i] != PROARGMODE_OUT &&
+				argmodes[i] != PROARGMODE_TABLE)
+				argnames[ninput++] = argnames[i];
+		}
+		numargs = ninput;
+	}
+
 	dpns.numargs = numargs;
 	dpns.argnames = argnames;
 
@@ -8815,7 +8833,8 @@ get_parameter(Param *param, deparse_context *context)
 		{
 			char	   *argname = dpns->argnames[param->paramid - 1];
 
-			if (argname)
+			/* An unnamed parameter has an empty name if others are named */
+			if (argname && argname[0] != '\0')
 			{
 				bool		should_qualify = false;
 				ListCell   *lc;
