aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-02-10 05:32:33 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-02-10 05:32:33 +0000
commit618733de1a3d08f63b42b92925d3845140eb6e02 (patch)
treef825fc827a9853482aaa3ad274d4a758c776844e /doc/src
parentaf0a15287de5ca254460ddefd4345cf62c577b5f (diff)
downloadpostgresql-618733de1a3d08f63b42b92925d3845140eb6e02.tar.gz
postgresql-618733de1a3d08f63b42b92925d3845140eb6e02.zip
Fix documentation of EXECUTE, add documentation of FOR ... EXECUTE.
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/plsql.sgml77
1 files changed, 53 insertions, 24 deletions
diff --git a/doc/src/sgml/plsql.sgml b/doc/src/sgml/plsql.sgml
index def5e07f084..72dabd824b0 100644
--- a/doc/src/sgml/plsql.sgml
+++ b/doc/src/sgml/plsql.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.18 2001/01/20 20:59:29 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.19 2001/02/10 05:32:33 tgl Exp $
-->
<chapter id="plsql">
@@ -54,26 +54,35 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.18 2001/01/20 20:59:29
</itemizedlist>
</para>
<para>
- The PL/pgSQL call handler parses the functions source text and
- produces an internal binary instruction tree on the first time the
+ The PL/pgSQL call handler parses the function's source text and
+ produces an internal binary instruction tree the first time the
function is called. The produced bytecode is identified
- in the call handler by the object ID of the function. This ensures,
+ in the call handler by the object ID of the function. This ensures
that changing a function by a DROP/CREATE sequence will take effect
without establishing a new database connection.
</para>
<para>
For all expressions and <acronym>SQL</acronym> statements used in
the function, the PL/pgSQL bytecode interpreter creates a
- prepared execution plan using the SPI managers SPI_prepare() and
- SPI_saveplan() functions. This is done the first time, the individual
+ prepared execution plan using the SPI manager's SPI_prepare() and
+ SPI_saveplan() functions. This is done the first time the individual
statement is processed in the PL/pgSQL function. Thus, a function with
conditional code that contains many statements for which execution
plans would be required, will only prepare and save those plans
- that are really used during the entire lifetime of the database
+ that are really used during the lifetime of the database
connection.
</para>
<para>
- Except for input-/output-conversion and calculation functions
+ 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.
+ </para>
+ <para>
+ Except for input/output conversion and calculation functions
for user defined types, anything that can be defined in C language
functions can also be done with PL/pgSQL. It is possible to
create complex conditional computation functions and later use
@@ -118,11 +127,13 @@ END;
</para>
<para>
- It is important not to misunderstand the meaning of BEGIN/END for
- grouping statements in PL/pgSQL and the database commands for
- transaction control. Functions and trigger procedures cannot
- start or commit transactions and <productname>Postgres</productname>
- does not have nested transactions.
+ It is important not to confuse the use of BEGIN/END for
+ grouping statements in PL/pgSQL with the database commands for
+ transaction control. PL/pgSQL's BEGIN/END are only for grouping;
+ they do not start or end a transaction. Functions and trigger procedures
+ are always executed within a transaction established by an outer query
+ --- they cannot start or commit transactions, since
+ <productname>Postgres</productname> does not have nested transactions.
</para>
</sect2>
@@ -146,8 +157,8 @@ END;
<para>
All variables, rows and records used in a block or its
- sub-blocks must be declared in the declarations section of a block
- except for the loop variable of a FOR loop iterating over a range
+ sub-blocks must be declared in the declarations section of a block,
+ except for the loop variable of a FOR-loop iterating over a range
of integer values. Parameters given to a PL/pgSQL function are
automatically declared with the usual identifiers $n.
The declarations have the following syntax:
@@ -439,7 +450,11 @@ CREATE FUNCTION logfunc2 (text) RETURNS timestamp AS '
SELECT INTO <replaceable>target</replaceable> <replaceable>expressions</replaceable> FROM ...;
</programlisting>
<replaceable>target</replaceable> can be a record, a row variable or a
- comma separated list of variables and record-/row-fields.
+ comma separated list of variables and record-/row-fields. Note that
+ this is quite different from Postgres' normal interpretation of
+ SELECT INTO, which is that the INTO target is a newly created table.
+ (If you want to create a table from a SELECT result inside a PL/pgSQL
+ function, use the equivalent syntax CREATE TABLE AS SELECT.)
</para>
<para>
if a row or a variable list is used as target, the selected values
@@ -506,10 +521,12 @@ PERFORM <replaceable>query</replaceable>
within the procedure to perform actions on variable tables and
fields.
</para>
-
+
<para>
- The results from SELECT queries are discarded by EXECUTE unless
- SELECT INTO is used to save the results into a table.
+ The results from SELECT queries are discarded by EXECUTE, and
+ SELECT INTO is not currently supported within EXECUTE. So, the
+ only way to extract a result from a dynamically-created SELECT
+ is to use the FOR ... EXECUTE form described later.
</para>
<para>
@@ -531,7 +548,7 @@ EXECUTE ''UPDATE tbl SET ''
<function>quote_literal()</function>. Both take the
appropriate steps to return the input text enclosed in single
or double quotes and with any embedded special characters
- intact.
+ properly escaped.
</para>
</listitem>
</varlistentry>
@@ -587,7 +604,7 @@ IF <replaceable>expression</replaceable> THEN
END IF;
</programlisting>
The <replaceable>expression</replaceable> must return a value that
- at least can be casted into a boolean type.
+ is a boolean or can be casted into a boolean.
</para>
</listitem>
</varlistentry>
@@ -635,9 +652,21 @@ FOR <replaceable>record | row</replaceable> IN <replaceable>select_clause</repla
END LOOP;
</programlisting>
The record or row is assigned all the rows resulting from the select
- clause and the statements executed for each. If the loop is terminated
- with an EXIT statement, the last assigned row is still accessible
- after the loop.
+ clause and the loop body is executed for each row. If the loop is
+ terminated with an EXIT statement, the last assigned row is still
+ accessible after the loop.
+ <programlisting>
+[&lt;&lt;label&gt;&gt;]
+FOR <replaceable>record | row</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP
+ <replaceable>statements</replaceable>
+END LOOP;
+ </programlisting>
+ This is like the previous form, except that the source SELECT
+ statement is specified as a string expression, which is evaluated
+ and re-planned on each entry to the FOR loop. This allows the
+ programmer to choose the speed of a pre-planned query or the
+ flexibility of a dynamic query, just as with a plain EXECUTE
+ statement.
<programlisting>
EXIT [ <replaceable>label</replaceable> ] [ WHEN <replaceable>expression</replaceable> ];
</programlisting>