Improve error messages for CREATE OR REPLACE PROCEDURE
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 8 Aug 2018 18:39:26 +0000 (20:39 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Sat, 18 Aug 2018 20:05:43 +0000 (22:05 +0200)
Change the hint to recommend DROP PROCEDURE instead of FUNCTION.  Also
make the error message when changing the return type more specific to
the case of procedures.

Reported-by: Jeremy Evans <code@jeremyevans.net>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
src/backend/catalog/pg_proc.c

index 9b4015d0d4a9e695bac5e76244b5f652d8708013..0c817047cd181241d11ed997b08a764f5e83d84a 100644 (file)
@@ -375,6 +375,7 @@ ProcedureCreate(const char *procedureName,
        Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
        Datum       proargnames;
        bool        isnull;
+       const char *dropcmd;
 
        if (!replace)
            ereport(ERROR,
@@ -400,16 +401,26 @@ ProcedureCreate(const char *procedureName,
                      errdetail("\"%s\" is a window function.", procedureName) :
                      0)));
 
+       dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" : "DROP FUNCTION");
+
        /*
         * Not okay to change the return type of the existing proc, since
         * existing rules, views, etc may depend on the return type.
+        *
+        * In case of a procedure, a changing return type means that whether
+        * the procedure has output parameters was changed.  Since there is no
+        * user visible return type, we produce a more specific error message.
         */
        if (returnType != oldproc->prorettype ||
            returnsSet != oldproc->proretset)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                    errmsg("cannot change return type of existing function"),
-                    errhint("Use DROP FUNCTION %s first.",
+                    prokind == PROKIND_PROCEDURE
+                    ? errmsg("cannot change whether a procedure has output parameters")
+                    : errmsg("cannot change return type of existing function"),
+                    /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+                    errhint("Use %s %s first.",
+                            dropcmd,
                             format_procedure(HeapTupleGetOid(oldtup)))));
 
        /*
@@ -434,7 +445,9 @@ ProcedureCreate(const char *procedureName,
                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                         errmsg("cannot change return type of existing function"),
                         errdetail("Row type defined by OUT parameters is different."),
-                        errhint("Use DROP FUNCTION %s first.",
+                        /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+                        errhint("Use %s %s first.",
+                                dropcmd,
                                 format_procedure(HeapTupleGetOid(oldtup)))));
        }
 
@@ -477,7 +490,9 @@ ProcedureCreate(const char *procedureName,
                            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                             errmsg("cannot change name of input parameter \"%s\"",
                                    old_arg_names[j]),
-                            errhint("Use DROP FUNCTION %s first.",
+                            /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+                            errhint("Use %s %s first.",
+                                    dropcmd,
                                     format_procedure(HeapTupleGetOid(oldtup)))));
            }
        }
@@ -501,7 +516,9 @@ ProcedureCreate(const char *procedureName,
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                         errmsg("cannot remove parameter defaults from existing function"),
-                        errhint("Use DROP FUNCTION %s first.",
+                        /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+                        errhint("Use %s %s first.",
+                                dropcmd,
                                 format_procedure(HeapTupleGetOid(oldtup)))));
 
            proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
@@ -527,7 +544,9 @@ ProcedureCreate(const char *procedureName,
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                             errmsg("cannot change data type of existing parameter default value"),
-                            errhint("Use DROP FUNCTION %s first.",
+                            /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+                            errhint("Use %s %s first.",
+                                    dropcmd,
                                     format_procedure(HeapTupleGetOid(oldtup)))));
                newlc = lnext(newlc);
            }