summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
authorTom Lane2005-04-07 14:53:04 +0000
committerTom Lane2005-04-07 14:53:04 +0000
commite00ee887612da0dab02f1a56e33d8ae821710e14 (patch)
tree29ceb4c0da3d21fb3d9f20aed0024314ff9eaa82 /src/pl
parent5c7c017b0708083c1f609344f51dbe1f1822ca0e (diff)
Allow plpgsql functions to omit RETURN command when the function returns
output parameters or VOID or a set. There seems no particular reason to insist on a RETURN in these cases, since the function return value is determined by other elements anyway. Per recent discussion.
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plpgsql/src/gram.y4
-rw-r--r--src/pl/plpgsql/src/pl_comp.c46
-rw-r--r--src/pl/plpgsql/src/pl_exec.c12
3 files changed, 51 insertions, 11 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 65b8f5f4093..8b5f6b5e28d 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.68 2005/04/05 18:05:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.69 2005/04/07 14:53:04 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -1071,7 +1071,7 @@ stmt_return : K_RETURN lno
else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
{
if (yylex() != ';')
- yyerror("function returning void cannot specify RETURN expression");
+ yyerror("RETURN cannot have a parameter in function returning void");
}
else if (plpgsql_curr_compile->fn_retistuple)
{
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 23109c949f7..9fefffa3196 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.86 2005/04/05 06:22:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.87 2005/04/07 14:53:04 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -271,8 +271,8 @@ do_compile(FunctionCallInfo fcinfo,
int parse_rc;
Oid rettypeid;
int numargs;
- int num_in_args;
- int num_out_args;
+ int num_in_args = 0;
+ int num_out_args = 0;
Oid *argtypes;
char **argnames;
char *argmodes;
@@ -374,7 +374,6 @@ do_compile(FunctionCallInfo fcinfo,
/*
* Create the variables for the procedure's parameters.
*/
- num_in_args = num_out_args = 0;
for (i = 0; i < numargs; i++)
{
char buf[32];
@@ -641,12 +640,48 @@ do_compile(FunctionCallInfo fcinfo,
parse_rc = plpgsql_yyparse();
if (parse_rc != 0)
elog(ERROR, "plpgsql parser returned %d", parse_rc);
+ function->action = plpgsql_yylval.program;
plpgsql_scanner_finish();
pfree(proc_source);
/*
- * If that was successful, complete the function's info.
+ * If it has OUT parameters or returns VOID or returns a set, we allow
+ * control to fall off the end without an explicit RETURN statement.
+ * The easiest way to implement this is to add a RETURN statement to the
+ * end of the statement list during parsing. However, if the outer block
+ * has an EXCEPTION clause, we need to make a new outer block, since the
+ * added RETURN shouldn't act like it is inside the EXCEPTION clause.
+ */
+ if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
+ function->fn_retset)
+ {
+ if (function->action->exceptions != NIL)
+ {
+ PLpgSQL_stmt_block *new;
+
+ new = palloc0(sizeof(PLpgSQL_stmt_block));
+ new->cmd_type = PLPGSQL_STMT_BLOCK;
+ new->body = list_make1(function->action);
+
+ function->action = new;
+ }
+ if (function->action->body == NIL ||
+ ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
+ {
+ PLpgSQL_stmt_return *new;
+
+ new = palloc0(sizeof(PLpgSQL_stmt_return));
+ new->cmd_type = PLPGSQL_STMT_RETURN;
+ new->expr = NULL;
+ new->retvarno = function->out_param_varno;
+
+ function->action->body = lappend(function->action->body, new);
+ }
+ }
+
+ /*
+ * Complete the function's info
*/
function->fn_nargs = procStruct->pronargs;
for (i = 0; i < function->fn_nargs; i++)
@@ -655,7 +690,6 @@ do_compile(FunctionCallInfo fcinfo,
function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
for (i = 0; i < plpgsql_nDatums; i++)
function->datums[i] = plpgsql_Datums[i];
- function->action = plpgsql_yylval.program;
/* Debug dump for completed functions */
if (plpgsql_DumpExecTree)
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 4454f2834a1..fe2d42ecf38 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.134 2005/04/05 06:22:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.135 2005/04/07 14:53:04 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -1691,12 +1691,18 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
&(estate->retisnull),
&(estate->rettype));
}
+
+ return PLPGSQL_RC_RETURN;
}
+ /*
+ * Special hack for function returning VOID: instead of NULL, return a
+ * non-null VOID value. This is of dubious importance but is kept for
+ * backwards compatibility. Note that the only other way to get here
+ * is to have written "RETURN NULL" in a function returning tuple.
+ */
if (estate->fn_rettype == VOIDOID)
{
- /* Special hack for function returning VOID */
- Assert(stmt->retvarno < 0 && stmt->expr == NULL);
estate->retval = (Datum) 0;
estate->retisnull = false;
estate->rettype = VOIDOID;