diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 998ed72089..a4cff1d3af 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,5 +1,5 @@ @@ -70,18 +70,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl As each expression and SQL query is first used - in the function, the PL/pgSQL interpreter creates a - prepared execution plan (using the SPI manager's - SPI_prepare and - SPI_saveplan 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 PL/pgSQL interpreter creates + a prepared execution plan (using the SPI + manager's SPI_prepare and + SPI_saveplan 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. Once PL/pgSQL has made a query plan for a particular @@ -110,14 +111,26 @@ END; - Because PL/pgSQL saves execution plans in this way, queries that appear - directly in a PL/pgSQL 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 PL/pgSQL - EXECUTE statement --- at the price of constructing a new query plan - on every execution. + Because PL/pgSQL saves execution plans + in this way, queries that appear directly in a + PL/pgSQL 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 PL/pgSQL EXECUTE statement --- at + the price of constructing a new query plan on every execution. + + + + The PL/pgSQL EXECUTE statement is not + related to the EXECUTE statement supported by the + PostgreSQL backend. The backend + EXECUTE statement cannot be used within PL/PgSQL functions (and + is not needed). + + + 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; Better Performance - SQL is the language PostgreSQL (and - most other Relational Databases) use as query - language. It's portable and easy to learn. But every - SQL statement must be executed - individually by the database server. + SQL is the language + PostgreSQL (and most other relational databases) + use as query language. It's portable and easy to learn. But + every SQL statement must be executed + individually by the database server. @@ -195,9 +208,10 @@ END; Portability - Because PL/pgSQL functions run inside PostgreSQL, these - functions will run on any platform where PostgreSQL - runs. Thus you can reuse code and have less development costs. + Because PL/pgSQL functions run inside + PostgreSQL, these functions will run on any + platform where PostgreSQL runs. Thus you can + reuse code and reduce development costs. @@ -227,16 +241,17 @@ END; - One good way to develop in PL/pgSQL is to simply use the text - editor of your choice to create your functions, and in another - console, use psql (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 CREATE OR REPLACE - FUNCTION. That way you can reload the file to update - the function definition. For example: + One good way to develop in PL/pgSQL is to simply + use the text editor of your choice to create your functions, and + in another window, use psql + (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 CREATE OR REPLACE + FUNCTION. That way you can reload the file to update the + function definition. For example: CREATE OR REPLACE FUNCTION testfunc(INTEGER) RETURNS INTEGER AS ' - .... + .... end; ' LANGUAGE 'plpgsql'; @@ -645,9 +660,9 @@ RENAME this_var TO that_var; - 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 PostgreSQL + 7.3. Fixing this is of low priority, since ALIAS covers most of + the practical uses of RENAME. @@ -898,7 +913,7 @@ END; PERFORM query; - This executes a SELECT + This executes a SELECT query and discards the result. PL/pgSQL variables are substituted in the query as usual. Also, the special variable @@ -1044,6 +1059,10 @@ END; Obtaining result status + There are several ways to determine the effect of a command. The + first method is to use the GET DIAGNOSTICS, + which has the form: + GET DIAGNOSTICS variable = item , ... ; @@ -1166,10 +1185,19 @@ RETURN expression; When a PL/pgSQL function is declared to return SETOF 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: + + +SELECT * FROM some_func(); + + + That is, the function is used as a table source in a FROM clause. RETURN NEXT expression; @@ -1184,6 +1212,24 @@ RETURN NEXT expression; RETURN, which need have no argument, causes control to exit the function. + + + + 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 + + @@ -1904,13 +1950,14 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id; Trigger Procedures - PL/pgSQL can be used to define trigger - procedures. A trigger procedure is created with the CREATE - FUNCTION command as a function with no arguments and a return - type of TRIGGER. Note that the function must be declared - with no arguments even if it expects to receive arguments specified - in CREATE TRIGGER --- trigger arguments are passed via - TG_ARGV, as described below. + PL/pgSQL can be used to define trigger + procedures. A trigger procedure is created with the + CREATE FUNCTION command as a function with no + arguments and a return type of TRIGGER. Note that + the function must be declared with no arguments even if it expects + to receive arguments specified in CREATE TRIGGER --- + trigger arguments are passed via TG_ARGV, as described + below. @@ -2106,14 +2153,15 @@ CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp - One painful detail in writing functions in PL/pgSQL is the handling - of single quotes. The function's source text in 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 PostgreSQL will be - forward compatible. + One painful detail in writing functions in + PL/pgSQL is the handling of single + quotes. The function's source text in 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 + PostgreSQL will be forward compatible. @@ -2504,7 +2552,7 @@ END; The following procedure grabs rows from a - SELECT statement and builds a large function + SELECT statement and builds a large function with the results in IF statements, for the sake of efficiency. Notice particularly the differences in cursors, FOR loops, and the need to escape @@ -2735,7 +2783,7 @@ show errors - If you do a LOCK TABLE in PL/pgSQL, the lock + If you do a LOCK TABLE in PL/pgSQL, the lock will not be released until the calling transaction is finished. @@ -2746,7 +2794,7 @@ show errors entire function (and other functions called from therein) is executed in a transaction and PostgreSQL rolls back the results if something goes wrong. Therefore only one - BEGIN statement is allowed. + BEGIN statement is allowed. @@ -2895,7 +2943,7 @@ END; EXECUTE - The PostgreSQL version of EXECUTE works + The PostgreSQL version of EXECUTE works nicely, but you have to remember to use quote_literal(TEXT) and quote_string(TEXT) as described in