mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Tweak SPI_cursor_open to allow INSERT/UPDATE/DELETE RETURNING; this was
merely a matter of fixing the error check, since the underlying Portal infrastructure already handles it. This in turn allows these statements to be used in some existing plpgsql and plperl contexts, such as a plpgsql FOR loop. Also, do some marginal code cleanup in places that were being sloppy about distinguishing SELECT from SELECT INTO.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.55 2006/05/30 11:40:21 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.56 2006/08/12 20:05:54 tgl Exp $ -->
|
||||
|
||||
<chapter id="plperl">
|
||||
<title>PL/Perl - Perl Procedural Language</title>
|
||||
@ -244,18 +244,8 @@ $$ LANGUAGE plperl;
|
||||
|
||||
SELECT * FROM perl_set();
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<application>PL/Perl</> does not currently have full support for
|
||||
domain types: it treats a domain the same as the underlying scalar
|
||||
type. This means that constraints associated with the domain will
|
||||
not be enforced. This is not an issue for function arguments, but
|
||||
it is a hazard if you declare a <application>PL/Perl</> function
|
||||
as returning a domain type.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you wish to use the <literal>strict</> pragma with your code,
|
||||
the easiest way to do so is to <command>SET</>
|
||||
@ -439,26 +429,26 @@ SELECT * from lotsa_md5(500);
|
||||
|
||||
<para>
|
||||
The advantage of prepared queries is that is it possible to use one prepared plan for more
|
||||
than one query execution. After the plan is not needed anymore, it must be freed with
|
||||
than one query execution. After the plan is not needed anymore, it may be freed with
|
||||
<literal>spi_freeplan</literal>:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<programlisting>
|
||||
CREATE OR REPLACE FUNCTION init() RETURNS INTEGER AS $$
|
||||
$_SHARED{my_plan} = spi_prepare( 'SELECT (now() + $1)::date AS now', 'INTERVAL');
|
||||
$_SHARED{my_plan} = spi_prepare( 'SELECT (now() + $1)::date AS now', 'INTERVAL');
|
||||
$$ LANGUAGE plperl;
|
||||
|
||||
CREATE OR REPLACE FUNCTION add_time( INTERVAL ) RETURNS TEXT AS $$
|
||||
return spi_exec_prepared(
|
||||
$_SHARED{my_plan},
|
||||
$_[0],
|
||||
)->{rows}->[0]->{now};
|
||||
return spi_exec_prepared(
|
||||
$_SHARED{my_plan},
|
||||
$_[0],
|
||||
)->{rows}->[0]->{now};
|
||||
$$ LANGUAGE plperl;
|
||||
|
||||
CREATE OR REPLACE FUNCTION done() RETURNS INTEGER AS $$
|
||||
spi_freeplan( $_SHARED{my_plan});
|
||||
undef $_SHARED{my_plan};
|
||||
spi_freeplan( $_SHARED{my_plan});
|
||||
undef $_SHARED{my_plan};
|
||||
$$ LANGUAGE plperl;
|
||||
|
||||
SELECT init();
|
||||
@ -478,16 +468,14 @@ SELECT done();
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>spi_cursor_close</literal> can be used to abort sequence of
|
||||
<literal>spi_fetchrow</literal> calls. Normally, the call to
|
||||
<literal>spi_fetchrow</literal> that returns <literal>undef</literal> is
|
||||
the signal that there are no more rows to read. Also
|
||||
that call automatically frees the cursor associated with the query. If it is desired not
|
||||
to read all retuned rows, <literal>spi_cursor_close</literal> must be
|
||||
called to avoid memory leaks.
|
||||
Normally, <function>spi_fetchrow</> should be repeated until it
|
||||
returns <literal>undef</literal>, indicating that there are no more
|
||||
rows to read. The cursor is automatically freed when
|
||||
<function>spi_fetchrow</> returns <literal>undef</literal>.
|
||||
If you do not wish to read all the rows, instead call
|
||||
<function>spi_cursor_close</> to free the cursor.
|
||||
Failure to do so will result in memory leaks.
|
||||
</para>
|
||||
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -630,8 +618,8 @@ CREATE FUNCTION badfunc() RETURNS integer AS $$
|
||||
return 1;
|
||||
$$ LANGUAGE plperl;
|
||||
</programlisting>
|
||||
The creation of this function will fail as its use of a forbidden
|
||||
operation will be be caught by the validator.
|
||||
The creation of this function will fail as its use of a forbidden
|
||||
operation will be be caught by the validator.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -748,8 +736,8 @@ $$ LANGUAGE plperl;
|
||||
<listitem>
|
||||
<para>
|
||||
Name of the table on which the trigger fired. This has been deprecated,
|
||||
and could be removed in a future release.
|
||||
Please use $_TD->{table_name} instead.
|
||||
and could be removed in a future release.
|
||||
Please use $_TD->{table_name} instead.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.97 2006/06/16 23:29:26 tgl Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.98 2006/08/12 20:05:54 tgl Exp $ -->
|
||||
|
||||
<chapter id="plpgsql">
|
||||
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
|
||||
@ -2040,9 +2040,8 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
|
||||
The <replaceable>target</replaceable> is a record variable, row variable,
|
||||
or comma-separated list of scalar variables.
|
||||
The <replaceable>target</replaceable> is successively assigned each row
|
||||
resulting from the <replaceable>query</replaceable> (which must be a
|
||||
<command>SELECT</command> command) and the loop body is executed for each
|
||||
row. Here is an example:
|
||||
resulting from the <replaceable>query</replaceable> and the loop body is
|
||||
executed for each row. Here is an example:
|
||||
<programlisting>
|
||||
CREATE FUNCTION cs_refresh_mviews() RETURNS integer AS $$
|
||||
DECLARE
|
||||
@ -2069,6 +2068,15 @@ $$ LANGUAGE plpgsql;
|
||||
assigned row value is still accessible after the loop.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <replaceable>query</replaceable> used in this type of <literal>FOR</>
|
||||
statement can be any query that returns rows to the caller:
|
||||
<command>SELECT</> (without <literal>INTO</>) is the most common case,
|
||||
but you can also use <command>INSERT</>, <command>UPDATE</>, or
|
||||
<command>DELETE</> with a <literal>RETURNING</> clause. Some utility
|
||||
commands such as <command>EXPLAIN</> will work too.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <literal>FOR-IN-EXECUTE</> statement is another way to iterate over
|
||||
rows:
|
||||
@ -2078,12 +2086,11 @@ FOR <replaceable>target</replaceable> IN EXECUTE <replaceable>text_expression</r
|
||||
<replaceable>statements</replaceable>
|
||||
END LOOP <optional> <replaceable>label</replaceable> </optional>;
|
||||
</synopsis>
|
||||
This is like the previous form, except that the source
|
||||
<command>SELECT</command> statement is specified as a string
|
||||
expression, which is evaluated and replanned on each entry to
|
||||
the <literal>FOR</> loop. This allows the programmer to choose the speed of
|
||||
a preplanned query or the flexibility of a dynamic query, just
|
||||
as with a plain <command>EXECUTE</command> statement.
|
||||
This is like the previous form, except that the source query
|
||||
is specified as a string expression, which is evaluated and replanned
|
||||
on each entry to the <literal>FOR</> loop. This allows the programmer to
|
||||
choose the speed of a preplanned query or the flexibility of a dynamic
|
||||
query, just as with a plain <command>EXECUTE</command> statement.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.45 2006/03/10 19:10:49 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.46 2006/08/12 20:05:54 tgl Exp $ -->
|
||||
|
||||
<chapter id="spi">
|
||||
<title>Server Programming Interface</title>
|
||||
@ -535,15 +535,15 @@ typedef struct
|
||||
<term><symbol>SPI_ERROR_TRANSACTION</symbol></term>
|
||||
<listitem>
|
||||
<para>
|
||||
if any command involving transaction manipulation was attempted
|
||||
(<command>BEGIN</>,
|
||||
<command>COMMIT</>,
|
||||
<command>ROLLBACK</>,
|
||||
<command>SAVEPOINT</>,
|
||||
<command>PREPARE TRANSACTION</>,
|
||||
<command>COMMIT PREPARED</>,
|
||||
<command>ROLLBACK PREPARED</>,
|
||||
or any variant thereof)
|
||||
if any command involving transaction manipulation was attempted
|
||||
(<command>BEGIN</>,
|
||||
<command>COMMIT</>,
|
||||
<command>ROLLBACK</>,
|
||||
<command>SAVEPOINT</>,
|
||||
<command>PREPARE TRANSACTION</>,
|
||||
<command>COMMIT PREPARED</>,
|
||||
<command>ROLLBACK PREPARED</>,
|
||||
or any variant thereof)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -917,10 +917,12 @@ bool SPI_is_cursor_plan(void * <parameter>plan</parameter>)
|
||||
<para>
|
||||
<function>SPI_is_cursor_plan</function> returns <symbol>true</symbol>
|
||||
if a plan prepared by <function>SPI_prepare</function> can be passed
|
||||
as an argument to <function>SPI_cursor_open</function> and <symbol>
|
||||
false</symbol> if that is not the case. The criteria are that the
|
||||
as an argument to <function>SPI_cursor_open</function>, or
|
||||
<symbol>false</symbol> if that is not the case. The criteria are that the
|
||||
<parameter>plan</parameter> represents one single command and that this
|
||||
command is a <command>SELECT</command> without an <command>INTO</command>
|
||||
command returns tuples to the caller; for example, <command>SELECT</>
|
||||
is allowed unless it contains an <literal>INTO</> clause, and
|
||||
<command>UPDATE</> is allowed only if it contains a <literal>RETURNING</>
|
||||
clause.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
Reference in New Issue
Block a user