Add trivial NULL statement to plpgsql, for Oracle compatibility.

This commit is contained in:
Tom Lane 2004-08-16 17:52:06 +00:00
parent bc91389df9
commit 64410289f8
2 changed files with 77 additions and 18 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.45 2004/08/08 22:40:46 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.46 2004/08/16 17:52:06 tgl Exp $
-->
<chapter id="plpgsql">
@ -1098,6 +1098,52 @@ PERFORM create_mv('cs_session_page_requests_mv', my_query);
</para>
</sect2>
<sect2 id="plpgsql-statements-null">
<title>Doing Nothing At All</title>
<para>
Sometimes a placeholder statement that does nothing is useful.
For example, it can indicate that one arm of an if/then/else
chain is deliberately empty. For this purpose, use the
<command>NULL</command> statement:
<synopsis>
NULL;
</synopsis>
</para>
<para>
For example, the following two fragments of code are equivalent:
<programlisting>
BEGIN
y := x / 0;
EXCEPTION
WHEN division_by_zero THEN
NULL; -- ignore the error
END;
</programlisting>
<programlisting>
BEGIN
y := x / 0;
EXCEPTION
WHEN division_by_zero THEN -- ignore the error
END;
</programlisting>
Which is preferable is a matter of taste.
</para>
<note>
<para>
In Oracle's PL/SQL, empty statement lists are not allowed, and so
<command>NULL</> statements are <emphasis>required</> for situations
such as this. <application>PL/pgSQL</application> allows you to
just write nothing, instead.
</para>
</note>
</sect2>
<sect2 id="plpgsql-statements-executing-dyn">
<title>Executing Dynamic Commands</title>
@ -1129,7 +1175,7 @@ EXECUTE <replaceable class="command">command-string</replaceable>;
<para>
When working with dynamic commands you will often have to handle escaping
of single quotes. The recommended method for quoting fixed text in your
function body is dollar quoting. If you have legacy code which does
function body is dollar quoting. If you have legacy code that does
not use dollar quoting, please refer to the
overview in <xref linkend="plpgsql-quote-tips">, which can save you
some effort when translating said code to a more reasonable scheme.
@ -1158,14 +1204,15 @@ EXECUTE <replaceable class="command">command-string</replaceable>;
</para>
<para>
An example (this assumes that you are using dollar quoting, so the
quote marks need not be doubled):
An example (this assumes that you are using dollar quoting for the
function as a whole, so the quote marks need not be doubled):
<programlisting>
EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
|| ' = '
|| quote_literal(newvalue)
|| ' WHERE ...';
|| ' WHERE key = '
|| quote_literal(keyvalue);
</programlisting>
</para>
@ -1193,7 +1240,8 @@ EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
|| ' = $$'
|| newvalue
|| '$$ WHERE ...';
|| '$$ WHERE key = '
|| quote_literal(keyvalue);
</programlisting>
because it would break if the contents of <literal>newvalue</>
happened to contain <literal>$$</>. The same objection would

View File

@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.59 2004/07/31 23:04:56 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.60 2004/08/16 17:52:06 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -132,7 +132,7 @@ static void check_assignable(PLpgSQL_datum *datum);
%type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
%type <stmt> stmt_for stmt_select stmt_perform
%type <stmt> stmt_dynexecute stmt_getdiag
%type <stmt> stmt_open stmt_fetch stmt_close
%type <stmt> stmt_open stmt_fetch stmt_close stmt_null
%type <exceptions> exception_sect proc_exceptions
%type <exception> proc_exception
@ -592,29 +592,31 @@ proc_sect :
proc_stmts : proc_stmts proc_stmt
{
if ($2 != NULL)
{
if ($1->stmts_used == $1->stmts_alloc)
{
$1->stmts_alloc *= 2;
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
}
$1->stmts[$1->stmts_used++] = $2;
$$ = $1;
}
$$ = $1;
}
| proc_stmt
{
PLpgSQL_stmts *new;
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
new->stmts_alloc = 64;
new->stmts_used = 1;
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
new->stmts[0] = $1;
new->stmts_alloc = 32;
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
$$ = new;
if ($1 != NULL)
new->stmts[new->stmts_used++] = $1;
$$ = new;
}
;
@ -654,6 +656,8 @@ proc_stmt : pl_block ';'
{ $$ = $1; }
| stmt_close
{ $$ = $1; }
| stmt_null
{ $$ = $1; }
;
stmt_perform : K_PERFORM lno expr_until_semi
@ -1493,6 +1497,13 @@ stmt_close : K_CLOSE lno cursor_variable ';'
}
;
stmt_null : K_NULL ';'
{
/* We do not bother building a node for NULL */
$$ = NULL;
}
;
cursor_varptr : T_SCALAR
{
if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)