@ -1,5 +1,5 @@
<!--
<!--
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.64 2005/04/05 18:05:45 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.65 2005/04/07 14:53:04 tgl Exp $
-->
-->
<chapter id="plpgsql">
<chapter id="plpgsql">
@ -673,7 +673,6 @@ $$ LANGUAGE plpgsql;
CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
BEGIN
BEGIN
tax := subtotal * 0.06;
tax := subtotal * 0.06;
RETURN;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
</programlisting>
</programlisting>
@ -691,7 +690,6 @@ CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$
BEGIN
BEGIN
sum := x + y;
sum := x + y;
prod := x * y;
prod := x * y;
RETURN;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
</programlisting>
</programlisting>
@ -742,7 +740,6 @@ CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement,
AS $$
AS $$
BEGIN
BEGIN
sum := v1 + v2 + v3;
sum := v1 + v2 + v3;
RETURN;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
</programlisting>
</programlisting>
@ -1498,17 +1495,20 @@ RETURN <replaceable>expression</replaceable>;
</para>
</para>
<para>
<para>
The return value of a function cannot be left undefined. If
If you declared the function to return <type>void</type>, a
control reaches the end of the top-level block of the function
<command>RETURN</command> statement can be used to exit the function
without hitting a <command>RETURN</command> statement, a run-time
early; but do not write an expression following
error will occur .
<command>RETURN</command> .
</para>
</para>
<para>
<para>
If you have declared the function to
The return value of a function cannot be left undefined. If
return <type>void</type>, a <command>RETURN</command> statement
control reaches the end of the top-level block of the function
must still be provided; but in this case the expression following
without hitting a <command>RETURN</command> statement, a run-time
<command>RETURN</command> is optional and will be ignored if present.
error will occur. This restriction does not apply to functions
with output parameters and functions returning <type>void</type>,
however. In those cases a <command>RETURN</command> statement is
automatically executed if the top-level block finishes.
</para>
</para>
</sect3>
</sect3>
@ -1538,7 +1538,8 @@ RETURN NEXT <replaceable>expression</replaceable>;
the <application>PL/pgSQL</> function. As successive
the <application>PL/pgSQL</> function. As successive
<command>RETURN NEXT</command> commands are executed, the result
<command>RETURN NEXT</command> commands are executed, the result
set is built up. A final <command>RETURN</command>, which should
set is built up. A final <command>RETURN</command>, which should
have no argument, causes control to exit the function.
have no argument, causes control to exit the function (or you can
just let control reach the end of the function).
</para>
</para>
<para>
<para>
@ -2424,7 +2425,6 @@ BEGIN
RETURN NEXT $1;
RETURN NEXT $1;
OPEN $2 FOR SELECT * FROM table_2;
OPEN $2 FOR SELECT * FROM table_2;
RETURN NEXT $2;
RETURN NEXT $2;
RETURN;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
@ -2990,7 +2990,8 @@ AFTER INSERT OR UPDATE OR DELETE ON sales_fact
<listitem>
<listitem>
<para>
<para>
In <productname>PostgreSQL</> you need to use dollar quoting or escape
In <productname>PostgreSQL</> the function body has to be written as
a string literal. Therefore you need to use dollar quoting or escape
single quotes in the function body. See <xref
single quotes in the function body. See <xref
linkend="plpgsql-quote-tips">.
linkend="plpgsql-quote-tips">.
</para>
</para>
@ -3027,8 +3028,8 @@ AFTER INSERT OR UPDATE OR DELETE ON sales_fact
<para>
<para>
Here is an <productname>Oracle</productname> <application>PL/SQL</> function:
Here is an <productname>Oracle</productname> <application>PL/SQL</> function:
<programlisting>
<programlisting>
CREATE OR REPLACE FUNCTION cs_fmt_browser_version(v_name IN varchar,
CREATE OR REPLACE FUNCTION cs_fmt_browser_version(v_name varchar,
v_version IN varchar)
v_version varchar)
RETURN varchar IS
RETURN varchar IS
BEGIN
BEGIN
IF v_version IS NULL THEN
IF v_version IS NULL THEN
@ -3042,21 +3043,10 @@ show errors;
</para>
</para>
<para>
<para>
Let's go through this function and see the differences to <application>PL/pgSQL</>:
Let's go through this function and see the differences compared to
<application>PL/pgSQL</>:
<itemizedlist>
<itemizedlist>
<listitem>
<para>
<productname>Oracle</productname> can have
<literal>IN</literal>, <literal>OUT</literal>, and
<literal>INOUT</literal> parameters passed to functions.
<literal>INOUT</literal>, for example, means that the
parameter will receive a value and return
another. <productname>PostgreSQL</> only has <literal>IN</literal>
parameters, and hence there is no specification of the parameter kind.
</para>
</listitem>
<listitem>
<listitem>
<para>
<para>
The <literal>RETURN</literal> key word in the function
The <literal>RETURN</literal> key word in the function
@ -3187,7 +3177,6 @@ BEGIN
|| ' LANGUAGE plpgsql;' ;
|| ' LANGUAGE plpgsql;' ;
EXECUTE func_cmd;
EXECUTE func_cmd;
RETURN;
END;
END;
$func$ LANGUAGE plpgsql;
$func$ LANGUAGE plpgsql;
</programlisting>
</programlisting>
@ -3209,8 +3198,8 @@ $func$ LANGUAGE plpgsql;
<para>
<para>
<xref linkend="plpgsql-porting-ex3"> shows how to port a function
<xref linkend="plpgsql-porting-ex3"> shows how to port a function
with <literal>OUT</> parameters and string manipulation.
with <literal>OUT</> parameters and string manipulation.
<productname>PostgreSQL</> does not have an
<productname>PostgreSQL</> does not have a built-i n
<function>instr</function> function, but you can work around it
<function>instr</function> function, but you can create one
using a combination of other
using a combination of other
functions.<indexterm><primary>instr</></indexterm> In <xref
functions.<indexterm><primary>instr</></indexterm> In <xref
linkend="plpgsql-porting-appendix"> there is a
linkend="plpgsql-porting-appendix"> there is a
@ -3227,9 +3216,6 @@ $func$ LANGUAGE plpgsql;
<para>
<para>
The following <productname>Oracle</productname> PL/SQL procedure is used
The following <productname>Oracle</productname> PL/SQL procedure is used
to parse a URL and return several elements (host, path, and query).
to parse a URL and return several elements (host, path, and query).
In <productname>PostgreSQL</>, functions can return only one value.
One way to work around this is to make the return value a composite
type (row type).
</para>
</para>
<para>
<para>
@ -3278,45 +3264,41 @@ show errors;
<para>
<para>
Here is a possible translation into <application>PL/pgSQL</>:
Here is a possible translation into <application>PL/pgSQL</>:
<programlisting>
<programlisting>
CREATE TYPE cs_parse_url_result AS (
CREATE OR REPLACE FUNCTION cs_parse_url(
v_host VARCHAR,
v_url IN VARCHAR,
v_path VARCHAR,
v_host OUT VARCHAR, -- This will be passed back
v_query VARCHAR
v_path OUT VARCHAR, -- This one too
);
v_query OUT VARCHAR) -- And this one
AS $$
CREATE OR REPLACE FUNCTION cs_parse_url(v_url VARCHAR)
RETURNS cs_parse_url_result AS $$
DECLARE
DECLARE
res cs_parse_url_result;
a_pos1 INTEGER;
a_pos1 INTEGER;
a_pos2 INTEGER;
a_pos2 INTEGER;
BEGIN
BEGIN
res. v_host := NULL;
v_host := NULL;
res. v_path := NULL;
v_path := NULL;
res. v_query := NULL;
v_query := NULL;
a_pos1 := instr(v_url, '//');
a_pos1 := instr(v_url, '//');
IF a_pos1 = 0 THEN
IF a_pos1 = 0 THEN
RETURN res ;
RETURN;
END IF;
END IF;
a_pos2 := instr(v_url, '/', a_pos1 + 2);
a_pos2 := instr(v_url, '/', a_pos1 + 2);
IF a_pos2 = 0 THEN
IF a_pos2 = 0 THEN
res. v_host := substr(v_url, a_pos1 + 2);
v_host := substr(v_url, a_pos1 + 2);
res. v_path := '/';
v_path := '/';
RETURN res ;
RETURN;
END IF;
END IF;
res. v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2);
v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2);
a_pos1 := instr(v_url, '?', a_pos2 + 1);
a_pos1 := instr(v_url, '?', a_pos2 + 1);
IF a_pos1 = 0 THEN
IF a_pos1 = 0 THEN
res. v_path := substr(v_url, a_pos2);
v_path := substr(v_url, a_pos2);
RETURN res ;
RETURN;
END IF;
END IF;
res.v_path := substr(v_url, a_pos2, a_pos1 - a_pos2);
v_path := substr(v_url, a_pos2, a_pos1 - a_pos2);
res.v_query := substr(v_url, a_pos1 + 1);
v_query := substr(v_url, a_pos1 + 1);
RETURN res;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
</programlisting>
</programlisting>
@ -3427,8 +3409,6 @@ BEGIN
WHEN unique_violation THEN <co id="co.plpgsql-porting-exception">
WHEN unique_violation THEN <co id="co.plpgsql-porting-exception">
-- don't worry if it already exists
-- don't worry if it already exists
END;
END;
RETURN;
END;
END;
$$ LANGUAGE plpgsql;
$$ LANGUAGE plpgsql;
</programlisting>
</programlisting>