diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 998ed72089e32f4b6849f878cda452ccfd1fbc1c..a4cff1d3af5c068f97e5e97bc08e8da2e47de4c0 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.7 2002/09/14 20:11:16 tgl Exp $ --> <chapter id="plpgsql"> @@ -70,18 +70,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl </para> <para> As each expression and <acronym>SQL</acronym> query is first used - in the function, the <application>PL/pgSQL</> interpreter creates a - prepared execution plan (using the <acronym>SPI</acronym> manager's - <function>SPI_prepare</function> and - <function>SPI_saveplan</function> functions). Subsequent visits - to that expression or query re-use the prepared plan. Thus, a function - with conditional code that contains many statements for which execution - plans might be required, will only prepare and save those plans - that are really used during the lifetime of the database - connection. This can provide a considerable savings of parsing - activity. A disadvantage is that errors in a specific expression - or query may not be detected until that part of the function is - reached in execution. + in the function, the <application>PL/pgSQL</> interpreter creates + a prepared execution plan (using the <acronym>SPI</acronym> + manager's <function>SPI_prepare</function> and + <function>SPI_saveplan</function> functions). Subsequent visits + to that expression or query re-use the prepared plan. Thus, a + function with conditional code that contains many statements for + which execution plans might be required will only prepare and save + those plans that are really used during the lifetime of the + database connection. This can substantially reduce the total + amount of time required to parse, and generate query plans for the + statements in a procedural language function. A disadvantage is + that errors in a specific expression or query may not be detected + until that part of the function is reached in execution. </para> <para> Once <application>PL/pgSQL</> has made a query plan for a particular @@ -110,14 +111,26 @@ END; </para> <para> - Because <application>PL/pgSQL</application> saves execution plans in this way, queries that appear - directly in a <application>PL/pgSQL</application> function must refer to the same tables and fields - on every execution; that is, you cannot use a parameter as the name of - a table or field in a query. To get around - this restriction, you can construct dynamic queries using the <application>PL/pgSQL</application> - EXECUTE statement --- at the price of constructing a new query plan - on every execution. + Because <application>PL/pgSQL</application> saves execution plans + in this way, queries that appear directly in a + <application>PL/pgSQL</application> function must refer to the + same tables and fields on every execution; that is, you cannot use + a parameter as the name of a table or field in a query. To get + around this restriction, you can construct dynamic queries using + the <application>PL/pgSQL</application> EXECUTE statement --- at + the price of constructing a new query plan on every execution. </para> + + <note> + <para> + The <application>PL/pgSQL</application> EXECUTE statement is not + related to the EXECUTE statement supported by the + <productname>PostgreSQL</productname> backend. The backend + EXECUTE statement cannot be used within PL/PgSQL functions (and + is not needed). + </para> + </note> + <para> Except for input/output conversion and calculation functions for user defined types, anything that can be defined in C language @@ -152,11 +165,11 @@ END; <title>Better Performance</title> <para> - <acronym>SQL</acronym> is the language <productname>PostgreSQL</> (and - most other Relational Databases) use as query - language. It's portable and easy to learn. But every - <acronym>SQL</acronym> statement must be executed - individually by the database server. + <acronym>SQL</acronym> is the language + <productname>PostgreSQL</> (and most other relational databases) + use as query language. It's portable and easy to learn. But + every <acronym>SQL</acronym> statement must be executed + individually by the database server. </para> <para> @@ -195,9 +208,10 @@ END; <title>Portability</title> <para> - Because <application>PL/pgSQL</application> functions run inside <productname>PostgreSQL</>, these - functions will run on any platform where <productname>PostgreSQL</> - runs. Thus you can reuse code and have less development costs. + Because <application>PL/pgSQL</application> functions run inside + <productname>PostgreSQL</>, these functions will run on any + platform where <productname>PostgreSQL</> runs. Thus you can + reuse code and reduce development costs. </para> </sect3> </sect2> @@ -227,16 +241,17 @@ END; </para> <para> - One good way to develop in <application>PL/pgSQL</> is to simply use the text - editor of your choice to create your functions, and in another - console, use <command>psql</command> (PostgreSQL's interactive monitor) to load - those functions. If you are doing it this way, it is a good - idea to write the function using <command>CREATE OR REPLACE - FUNCTION</command>. That way you can reload the file to update - the function definition. For example: + One good way to develop in <application>PL/pgSQL</> is to simply + use the text editor of your choice to create your functions, and + in another window, use <command>psql</command> + (<productname>PostgreSQL</>'s interactive monitor) to load those + functions. If you are doing it this way, it is a good idea to + write the function using <command>CREATE OR REPLACE + FUNCTION</>. That way you can reload the file to update the + function definition. For example: <programlisting> CREATE OR REPLACE FUNCTION testfunc(INTEGER) RETURNS INTEGER AS ' - .... + .... end; ' LANGUAGE 'plpgsql'; </programlisting> @@ -645,9 +660,9 @@ RENAME this_var TO that_var; <note> <para> - RENAME appears to be broken as of PostgreSQL 7.2. Fixing this is - of low priority, since ALIAS covers most of the practical uses of - RENAME. + RENAME appears to be broken as of <productname>PostgreSQL</> + 7.3. Fixing this is of low priority, since ALIAS covers most of + the practical uses of RENAME. </para> </note> @@ -898,7 +913,7 @@ END; PERFORM <replaceable>query</replaceable>; </synopsis> - This executes a <literal>SELECT</literal> + This executes a <command>SELECT</command> <replaceable>query</replaceable> and discards the result. <application>PL/pgSQL</application> variables are substituted in the query as usual. Also, the special variable @@ -1044,6 +1059,10 @@ END; <title>Obtaining result status</title> <para> + There are several ways to determine the effect of a command. The + first method is to use the <literal>GET DIAGNOSTICS</literal>, + which has the form: + <synopsis> GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replaceable> <optional> , ... </optional> ; </synopsis> @@ -1166,10 +1185,19 @@ RETURN <replaceable>expression</replaceable>; <para> When a <application>PL/pgSQL</> function is declared to return <literal>SETOF</literal> <replaceable>sometype</>, the procedure - to follow is slightly different. The individual items to be returned - are specified in RETURN NEXT commands, and then a final RETURN with - no argument is given to indicate that the function is done generating - items. + to follow is slightly different. In that case, the individual + items to return are specified in RETURN NEXT commands, and then a + final RETURN command with no arguments is used to indicate that + the function has finished executing. RETURN NEXT can be used with + both scalar and composite data types; in the later case, an + entire "table" of results will be returned. Functions that use + RETURN NEXT should be called in the following fashion: + +<programlisting> +SELECT * FROM some_func(); +</programlisting> + + That is, the function is used as a table source in a FROM clause. <synopsis> RETURN NEXT <replaceable>expression</replaceable>; @@ -1184,6 +1212,24 @@ RETURN NEXT <replaceable>expression</replaceable>; RETURN, which need have no argument, causes control to exit the function. </para> + + <note> + <para> + The current implementation of RETURN NEXT for PL/PgSQL stores + the entire result set before returning from the function, as + discussed above. That means that if a PL/PgSQL function + produces a very large result set, performance may be poor: data + will be written to disk to avoid memory exhaustion, but the + function itself will not return until the entire + result set has been generated. A future version of PL/PgSQL may + allow users to allow users to define set-returning functions + that do not have this limitation. Currently, the point at which + data begins being written to disk is controlled by the + <option>SORT_MEM</> configuration variable. Administrators who + have sufficient memory to store larger result sets in memory + should consider increasing this parameter. + </para> + </note> </sect2> <sect2 id="plpgsql-conditionals"> @@ -1904,13 +1950,14 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id; <title>Trigger Procedures</title> <para> - <application>PL/pgSQL</application> can be used to define trigger - procedures. A trigger procedure is created with the <command>CREATE - FUNCTION</command> command as a function with no arguments and a return - type of <type>TRIGGER</type>. Note that the function must be declared - with no arguments even if it expects to receive arguments specified - in <command>CREATE TRIGGER</> --- trigger arguments are passed via - <varname>TG_ARGV</>, as described below. + <application>PL/pgSQL</application> can be used to define trigger + procedures. A trigger procedure is created with the + <command>CREATE FUNCTION</> command as a function with no + arguments and a return type of <type>TRIGGER</type>. Note that + the function must be declared with no arguments even if it expects + to receive arguments specified in <command>CREATE TRIGGER</> --- + trigger arguments are passed via <varname>TG_ARGV</>, as described + below. </para> <para> @@ -2106,14 +2153,15 @@ CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp </para> <para> - One painful detail in writing functions in <application>PL/pgSQL</application> is the handling - of single quotes. The function's source text in <command>CREATE FUNCTION</command> must - be a literal string. Single quotes inside of literal strings must be - either doubled or quoted with a backslash. We are still looking for - an elegant alternative. In the meantime, doubling the single quotes - as in the examples below should be used. Any solution for this - in future versions of <productname>PostgreSQL</productname> will be - forward compatible. + One painful detail in writing functions in + <application>PL/pgSQL</application> is the handling of single + quotes. The function's source text in <command>CREATE FUNCTION</> + must be a literal string. Single quotes inside of literal strings + must be either doubled or quoted with a backslash. We are still + looking for an elegant alternative. In the meantime, doubling the + single quotes as in the examples below should be used. Any + solution for this in future versions of + <productname>PostgreSQL</productname> will be forward compatible. </para> <para> @@ -2504,7 +2552,7 @@ END; <para> The following procedure grabs rows from a - <literal>SELECT</literal> statement and builds a large function + <command>SELECT</command> statement and builds a large function with the results in <literal>IF</literal> statements, for the sake of efficiency. Notice particularly the differences in cursors, <literal>FOR</literal> loops, and the need to escape @@ -2735,7 +2783,7 @@ show errors <callout arearefs="co.plpgsql-porting-locktable"> <para> - If you do a <literal>LOCK TABLE</literal> in <application>PL/pgSQL</>, the lock + If you do a <command>LOCK TABLE</command> in <application>PL/pgSQL</>, the lock will not be released until the calling transaction is finished. </para> </callout> @@ -2746,7 +2794,7 @@ show errors entire function (and other functions called from therein) is executed in a transaction and <productname>PostgreSQL</> rolls back the results if something goes wrong. Therefore only one - <literal>BEGIN</literal> statement is allowed. + <command>BEGIN</command> statement is allowed. </para> </callout> @@ -2895,7 +2943,7 @@ END; <title>EXECUTE</title> <para> - The <productname>PostgreSQL</> version of <literal>EXECUTE</literal> works + The <productname>PostgreSQL</> version of <command>EXECUTE</command> works nicely, but you have to remember to use <function>quote_literal(TEXT)</function> and <function>quote_string(TEXT)</function> as described in <xref