SELECT init();
SELECT add_time('1 day'), add_time('2 days'), add_time('3 days');
SELECT done();
add_time | add_time | add_time
------------+------------+------------
2005-12-10 | 2005-12-11 | 2005-12-12
</programlisting>
Note that the parameter subscript in <literal>spi_prepare</literal> is defined via
$1, $2, $3, etc., so avoid declaring query strings in double quotes that might easily
lead to hard-to-catch bugs.
</para>
<para>
Another example illustrates usage of an optional parameter in <literal>spi_exec_prepared</literal>:
<programlisting>
CREATE TABLE hosts AS SELECT id, ('192.168.1.'||id)::inet AS address
FROM generate_series(1,3) AS id;
CREATE OR REPLACE FUNCTION init_hosts_query() RETURNS VOID AS $$
$_SHARED{plan} = spi_prepare('SELECT * FROM hosts
WHERE address << $1', 'inet');
$$ LANGUAGE plperl;
CREATE OR REPLACE FUNCTION query_hosts(inet) RETURNS SETOF hosts AS $$
return spi_exec_prepared(
$_SHARED{plan},
{limit => 2},
$_[0]
)->{rows};
$$ LANGUAGE plperl;
CREATE OR REPLACE FUNCTION release_hosts_query() RETURNS VOID AS $$
spi_freeplan($_SHARED{plan});
undef $_SHARED{plan};
$$ LANGUAGE plperl;
SELECT init_hosts_query();
SELECT query_hosts('192.168.1.0/30');
SELECT release_hosts_query();
query_hosts
-----------------
(1,192.168.1.1)
(2,192.168.1.2)
(2 rows)
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal><function>spi_commit()</function></literal>
<indexterm>
<primary>spi_commit</primary>
<secondary>in PL/Perl</secondary>
</indexterm>
</term>
<term>
<literal><function>spi_rollback()</function></literal>
<indexterm>
<primary>spi_rollback</primary>
<secondary>in PL/Perl</secondary>
</indexterm>
</term>
<listitem>
<para>
Commit or roll back the current transaction. This can only be called
in a procedure or anonymous code block (<command>DO</command> command)
called from the top level. (Note that it is not possible to run the
SQL commands <command>COMMIT</command> or <command>ROLLBACK</command>
via <function>spi_exec_query</function> or similar. It has to be done
using these functions.) After a transaction is ended, a new
transaction is automatically started, so there is no separate function
for that.
</para>
<para>
Here is an example:
<programlisting>
CREATE PROCEDURE transaction_test1()
LANGUAGE plperl
AS $$
foreach my $i (0..9) {
spi_exec_query("INSERT INTO test1 (a) VALUES ($i)");
if ($i % 2 == 0) {
spi_commit();
} else {
spi_rollback();
}
}
$$;
CALL transaction_test1();
</programlisting>
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="plperl-utility-functions">
<title>Utility Functions in PL/Perl</title>
<variablelist>
<varlistentry>
<term>
<literal><function>elog(<replaceable>level</replaceable>, <replaceable>msg</replaceable>)</function></literal>
<indexterm>
<primary>elog</primary>
<secondary>in PL/Perl</secondary>
</indexterm>
</term>
<listitem>
<para>
Emit a log or error message. Possible levels are
<literal>DEBUG</literal>, <literal>LOG</literal>, <literal>INFO</literal>,
<literal>NOTICE</literal>, <literal>WARNING</literal>, and <literal>ERROR</literal>.
<literal>ERROR</literal>
raises an error condition; if this is not trapped by the surrounding
Perl code, the error propagates out to the calling query, causing
the current transaction or subtransaction to be aborted. This
is effectively the same as the Perl <literal>die</literal> command.
The other levels only generate messages of