summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/plpgsql.sgml20
-rw-r--r--src/pl/plpgsql/src/pl_exec.c10
2 files changed, 23 insertions, 7 deletions
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 30d1c64af5..80dbf45327 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1904,8 +1904,8 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
indefinitely until terminated by an <literal>EXIT</> or
<command>RETURN</command> statement. The optional
<replaceable>label</replaceable> can be used by <literal>EXIT</>
- and <literal>CONTINUE</literal> statements in nested loops to
- specify which loop the statement should be applied to.
+ and <literal>CONTINUE</literal> statements within nested loops to
+ specify which loop those statements refer to.
</para>
</sect3>
@@ -1939,9 +1939,19 @@ EXIT <optional> <replaceable>label</replaceable> </optional> <optional> WHEN <re
<para>
<literal>EXIT</> can be used with all types of loops; it is
- not limited to use with unconditional loops. When used with a
+ not limited to use with unconditional loops.
+ </para>
+
+ <para>
+ When used with a
<literal>BEGIN</literal> block, <literal>EXIT</literal> passes
control to the next statement after the end of the block.
+ Note that a label must be used for this purpose; an unlabelled
+ <literal>EXIT</literal> is never considered to match a
+ <literal>BEGIN</literal> block. (This is a change from
+ pre-8.4 releases of <productname>PostgreSQL</productname>, which
+ would allow an unlabelled <literal>EXIT</literal> to match
+ a <literal>BEGIN</literal> block.)
</para>
<para>
@@ -1959,11 +1969,13 @@ LOOP
EXIT WHEN count &gt; 0; -- same result as previous example
END LOOP;
+&lt;&lt;ablock&gt;&gt;
BEGIN
-- some computations
IF stocks &gt; 100000 THEN
- EXIT; -- causes exit from the BEGIN block
+ EXIT ablock; -- causes exit from the BEGIN block
END IF;
+ -- computations here will be skipped when stocks &gt; 100000
END;
</programlisting>
</para>
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 1ba342f20d..77d0e8fad4 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1145,11 +1145,15 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
return rc;
case PLPGSQL_RC_EXIT:
+ /*
+ * This is intentionally different from the handling of RC_EXIT
+ * for loops: to match a block, we require a match by label.
+ */
if (estate->exitlabel == NULL)
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_EXIT;
if (block->label == NULL)
return PLPGSQL_RC_EXIT;
- if (strcmp(block->label, estate->exitlabel))
+ if (strcmp(block->label, estate->exitlabel) != 0)
return PLPGSQL_RC_EXIT;
estate->exitlabel = NULL;
return PLPGSQL_RC_OK;
@@ -1604,7 +1608,7 @@ exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
return PLPGSQL_RC_OK;
if (stmt->label == NULL)
return PLPGSQL_RC_EXIT;
- if (strcmp(stmt->label, estate->exitlabel))
+ if (strcmp(stmt->label, estate->exitlabel) != 0)
return PLPGSQL_RC_EXIT;
estate->exitlabel = NULL;
return PLPGSQL_RC_OK;