2000-03-31 05:27:42 +02:00
|
|
|
<!--
|
2001-10-13 06:23:50 +02:00
|
|
|
$Header: /cvsroot/pgsql/doc/src/sgml/pltcl.sgml,v 2.15 2001/10/13 04:23:50 momjian Exp $
|
2000-03-31 05:27:42 +02:00
|
|
|
-->
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<chapter id="pltcl">
|
2001-09-10 23:58:47 +02:00
|
|
|
<title>PL/Tcl - Tcl Procedural Language</title>
|
2000-03-31 00:13:30 +02:00
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm zone="pltcl">
|
|
|
|
<primary>PL/Tcl</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
|
|
|
<indexterm zone="pltcl">
|
|
|
|
<primary>Tcl</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
2000-03-31 00:13:30 +02:00
|
|
|
<para>
|
|
|
|
PL/Tcl is a loadable procedural language for the
|
|
|
|
<productname>Postgres</productname> database system
|
|
|
|
that enables the Tcl language to be used to create functions and
|
2001-02-09 04:06:38 +01:00
|
|
|
trigger procedures.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
This package was originally written by Jan Wieck.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<!-- **** PL/Tcl overview **** -->
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="pltcl-overview">
|
2000-03-31 00:13:30 +02:00
|
|
|
<title>Overview</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
PL/Tcl offers most of the capabilities a function
|
|
|
|
writer has in the C language, except for some restrictions.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-02-09 04:06:38 +01:00
|
|
|
The good restriction is that everything is executed in a safe
|
|
|
|
Tcl interpreter. In addition to the limited command set of safe Tcl, only
|
|
|
|
a few commands are available to access the database via SPI and to raise
|
2001-09-10 23:58:47 +02:00
|
|
|
messages via <function>elog()</>. There is no way to access internals of the
|
2001-02-09 04:06:38 +01:00
|
|
|
database backend or to gain OS-level access under the permissions of the
|
|
|
|
<productname>Postgres</productname> user ID, as a C function can do.
|
2000-03-31 00:13:30 +02:00
|
|
|
Thus, any unprivileged database user may be
|
|
|
|
permitted to use this language.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-02-09 04:06:38 +01:00
|
|
|
The other, implementation restriction is that Tcl procedures cannot
|
|
|
|
be used to create input/output functions for new data types.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
<para>
|
2001-02-09 04:06:38 +01:00
|
|
|
Sometimes it is desirable to write Tcl functions that are not restricted
|
|
|
|
to safe Tcl --- for example, one might want a Tcl function that sends
|
|
|
|
mail. To handle these cases, there is a variant of PL/Tcl called PL/TclU
|
|
|
|
(for untrusted Tcl). This is the exact same language except that a full
|
|
|
|
Tcl interpreter is used. <emphasis>If PL/TclU is used, it must be
|
|
|
|
installed as an untrusted procedural language</emphasis> so that only
|
|
|
|
database superusers can create functions in it. The writer of a PL/TclU
|
|
|
|
function must take care that the function cannot be used to do anything
|
|
|
|
unwanted, since it will be able to do anything that could be done by
|
|
|
|
a user logged in as the database administrator.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
The shared object for the PL/Tcl and PL/TclU call handlers is
|
|
|
|
automatically built and installed in the
|
|
|
|
<productname>Postgres</productname>
|
|
|
|
library directory if Tcl/Tk support is specified
|
|
|
|
in the configuration step of the installation procedure. To install
|
|
|
|
PL/Tcl and/or PL/TclU in a particular database, use the
|
|
|
|
<filename>createlang</filename> script.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- **** PL/Tcl description **** -->
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="pltcl-description">
|
2000-03-31 00:13:30 +02:00
|
|
|
<title>Description</title>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title><productname>Postgres</productname> Functions and Tcl Procedure Names</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
In <productname>Postgres</productname>, one and the
|
|
|
|
same function name can be used for
|
|
|
|
different functions as long as the number of arguments or their types
|
|
|
|
differ. This would collide with Tcl procedure names. To offer the same
|
|
|
|
flexibility in PL/Tcl, the internal Tcl procedure names contain the object
|
2001-02-09 04:06:38 +01:00
|
|
|
ID of the procedure's pg_proc row as part of their name. Thus, different
|
2000-03-31 00:13:30 +02:00
|
|
|
argtype versions of the same <productname>Postgres</productname>
|
|
|
|
function are different for Tcl too.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Defining Functions in PL/Tcl</title>
|
|
|
|
|
|
|
|
<para>
|
2001-02-09 04:06:38 +01:00
|
|
|
To create a function in the PL/Tcl language, use the standard syntax
|
2000-03-31 00:13:30 +02:00
|
|
|
|
|
|
|
<programlisting>
|
2001-02-09 04:06:38 +01:00
|
|
|
CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-types</replaceable>) RETURNS <replaceable>return-type</replaceable> AS '
|
2000-03-31 00:13:30 +02:00
|
|
|
# PL/Tcl function body
|
|
|
|
' LANGUAGE 'pltcl';
|
|
|
|
</programlisting>
|
|
|
|
|
2001-02-09 04:06:38 +01:00
|
|
|
When the function is called, the arguments are given as
|
2001-05-01 00:22:34 +02:00
|
|
|
variables <literal>$1</literal> ... <literal>$n</literal> to the
|
|
|
|
Tcl procedure body. The result is returned
|
|
|
|
from the Tcl code in the usual way, with a <literal>return</literal>
|
|
|
|
statement. For example, a function
|
2001-02-09 04:06:38 +01:00
|
|
|
returning the higher of two int4 values could be defined as:
|
2000-03-31 00:13:30 +02:00
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
CREATE FUNCTION tcl_max (int4, int4) RETURNS int4 AS '
|
|
|
|
if {$1 > $2} {return $1}
|
|
|
|
return $2
|
|
|
|
' LANGUAGE 'pltcl';
|
|
|
|
</programlisting>
|
|
|
|
|
2001-05-01 00:22:34 +02:00
|
|
|
To return a NULL value from a PL/Tcl function, execute
|
|
|
|
<literal>return_null</literal>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-03-31 00:13:30 +02:00
|
|
|
Composite type arguments are given to the procedure as Tcl arrays.
|
|
|
|
The element names
|
|
|
|
in the array are the attribute names of the composite
|
|
|
|
type. If an attribute in the actual row
|
|
|
|
has the NULL value, it will not appear in the array! Here is
|
|
|
|
an example that defines the overpaid_2 function (as found in the
|
|
|
|
older <productname>Postgres</productname> documentation) in PL/Tcl
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
|
|
|
|
if {200000.0 < $1(salary)} {
|
|
|
|
return "t"
|
|
|
|
}
|
|
|
|
if {$1(age) < 30 && 100000.0 < $1(salary)} {
|
|
|
|
return "t"
|
|
|
|
}
|
|
|
|
return "f"
|
|
|
|
' LANGUAGE 'pltcl';
|
|
|
|
</programlisting>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Global Data in PL/Tcl</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Sometimes (especially when using the SPI functions described later) it
|
|
|
|
is useful to have some global status data that is held between two
|
2001-02-09 04:06:38 +01:00
|
|
|
calls to a procedure. This is easily done since
|
|
|
|
all PL/Tcl procedures executed in one backend share the same
|
2000-03-31 00:13:30 +02:00
|
|
|
safe Tcl interpreter.
|
2001-02-09 04:06:38 +01:00
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
To help protect PL/Tcl procedures from unwanted side effects,
|
2001-09-10 23:58:47 +02:00
|
|
|
an array is made available to each procedure via the <function>upvar</>
|
2001-02-09 04:06:38 +01:00
|
|
|
command. The global name of this variable is the procedure's internal
|
|
|
|
name and the local name is GD. It is recommended that GD be used
|
|
|
|
for private status data of a procedure. Use regular Tcl global variables
|
|
|
|
only for values that you specifically intend to be shared among multiple
|
|
|
|
procedures.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Trigger Procedures in PL/Tcl</title>
|
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
|
|
|
<primary>triggers</primary>
|
|
|
|
<secondary>in PL/Tcl</secondary>
|
|
|
|
</indexterm>
|
|
|
|
|
2000-03-31 00:13:30 +02:00
|
|
|
<para>
|
|
|
|
Trigger procedures are defined in <productname>Postgres</productname>
|
|
|
|
as functions without
|
|
|
|
arguments and a return type of opaque. And so are they in the PL/Tcl
|
|
|
|
language.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-02-09 04:06:38 +01:00
|
|
|
The information from the trigger manager is given to the procedure body
|
2000-03-31 00:13:30 +02:00
|
|
|
in the following variables:
|
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_name</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The name of the trigger from the CREATE TRIGGER statement.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_relid</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The object ID of the table that caused the trigger procedure
|
|
|
|
to be invoked.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_relatts</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
A Tcl list of the tables field names prefixed with an empty list element.
|
2001-09-10 23:58:47 +02:00
|
|
|
So looking up an element name in the list with the <function>lsearch</> Tcl command
|
2000-03-31 00:13:30 +02:00
|
|
|
returns the same positive number starting from 1 as the fields are numbered
|
|
|
|
in the pg_attribute system catalog.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_when</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The string BEFORE or AFTER depending on the event of the trigger call.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_level</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The string ROW or STATEMENT depending on the event of the trigger call.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$TG_op</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The string INSERT, UPDATE or DELETE depending on the event of the
|
|
|
|
trigger call.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$NEW</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
An array containing the values of the new table row on INSERT/UPDATE
|
|
|
|
actions, or empty on DELETE.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$OLD</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
An array containing the values of the old table row on UPDATE/DELETE
|
|
|
|
actions, or empty on INSERT.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$GD</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
The global status data array as described above.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term><replaceable class="Parameter">$args</replaceable></term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
A Tcl list of the arguments to the procedure as given in the
|
|
|
|
CREATE TRIGGER statement. The arguments are also accessible as $1 ... $n
|
|
|
|
in the procedure body.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
</variablelist>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The return value from a trigger procedure is one of the strings OK or SKIP,
|
|
|
|
or a list as returned by the 'array get' Tcl command. If the return value
|
|
|
|
is OK, the normal operation (INSERT/UPDATE/DELETE) that fired this trigger
|
|
|
|
will take place. Obviously, SKIP tells the trigger manager to silently
|
|
|
|
suppress the operation. The list from 'array get' tells PL/Tcl
|
|
|
|
to return a modified row to the trigger manager that will be inserted instead
|
|
|
|
of the one given in $NEW (INSERT/UPDATE only). Needless to say that all
|
|
|
|
this is only meaningful when the trigger is BEFORE and FOR EACH ROW.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
Here's a little example trigger procedure that forces an integer value
|
2001-02-09 04:06:38 +01:00
|
|
|
in a table to keep track of the number of updates that are performed on the
|
|
|
|
row. For new rows inserted, the value is initialized to 0 and then
|
2000-03-31 00:13:30 +02:00
|
|
|
incremented on every update operation:
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
CREATE FUNCTION trigfunc_modcount() RETURNS OPAQUE AS '
|
|
|
|
switch $TG_op {
|
|
|
|
INSERT {
|
|
|
|
set NEW($1) 0
|
|
|
|
}
|
|
|
|
UPDATE {
|
|
|
|
set NEW($1) $OLD($1)
|
|
|
|
incr NEW($1)
|
|
|
|
}
|
|
|
|
default {
|
|
|
|
return OK
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [array get NEW]
|
|
|
|
' LANGUAGE 'pltcl';
|
|
|
|
|
2000-08-25 17:17:50 +02:00
|
|
|
CREATE TABLE mytab (num int4, modcnt int4, description text);
|
2000-03-31 00:13:30 +02:00
|
|
|
|
|
|
|
CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
|
|
|
|
FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Database Access from PL/Tcl</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The following commands are available to access the database from
|
|
|
|
the body of a PL/Tcl procedure:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
|
|
|
|
<varlistentry>
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
|
|
|
<primary>elog</primary>
|
|
|
|
</indexterm>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>elog</> <replaceable>level</replaceable> <replaceable>msg</replaceable></term>
|
2000-03-31 00:13:30 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2000-05-18 16:24:38 +02:00
|
|
|
Fire a log message. Possible levels are NOTICE, ERROR,
|
2001-06-09 04:19:07 +02:00
|
|
|
FATAL, and DEBUG
|
2001-02-09 04:06:38 +01:00
|
|
|
as for the <function>elog</function> C function.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>quote</> <replaceable>string</replaceable></term>
|
2000-03-31 00:13:30 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2001-03-25 12:16:12 +02:00
|
|
|
Duplicates all occurrences of single quote and backslash characters.
|
2000-03-31 00:13:30 +02:00
|
|
|
It should be used when variables are used in the query string given
|
|
|
|
to <function>spi_exec</function> or
|
|
|
|
<function>spi_prepare</function> (not for the value list on
|
|
|
|
<function>spi_execp</function>).
|
|
|
|
Think about a query string like
|
|
|
|
|
2001-09-13 17:55:24 +02:00
|
|
|
<programlisting>
|
2000-03-31 00:13:30 +02:00
|
|
|
"SELECT '$val' AS ret"
|
2001-09-13 17:55:24 +02:00
|
|
|
</programlisting>
|
2000-03-31 00:13:30 +02:00
|
|
|
|
2001-09-13 17:55:24 +02:00
|
|
|
where the Tcl variable val actually contains <literal>doesn't</literal>. This would result
|
2000-03-31 00:13:30 +02:00
|
|
|
in the final query string
|
|
|
|
|
2001-09-13 17:55:24 +02:00
|
|
|
<programlisting>
|
|
|
|
SELECT 'doesn't' AS ret
|
|
|
|
</programlisting>
|
2000-03-31 00:13:30 +02:00
|
|
|
|
2001-02-09 04:06:38 +01:00
|
|
|
which would cause a parse error during
|
2000-03-31 00:13:30 +02:00
|
|
|
<function>spi_exec</function> or
|
|
|
|
<function>spi_prepare</function>.
|
|
|
|
It should contain
|
|
|
|
|
2001-09-13 17:55:24 +02:00
|
|
|
<programlisting>
|
|
|
|
SELECT 'doesn''t' AS ret
|
|
|
|
</programlisting>
|
2000-03-31 00:13:30 +02:00
|
|
|
|
|
|
|
and has to be written as
|
|
|
|
|
2001-09-13 17:55:24 +02:00
|
|
|
<programlisting>
|
|
|
|
SELECT '[ quote $val ]' AS ret
|
|
|
|
</programlisting>
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
2001-08-02 17:45:55 +02:00
|
|
|
<varlistentry>
|
|
|
|
<indexterm>
|
|
|
|
<primary>spi_lastoid</primary>
|
|
|
|
</indexterm>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>spi_lastoid</></term>
|
2001-08-02 17:45:55 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Returns the OID of the last query if it was an INSERT.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
2000-03-31 00:13:30 +02:00
|
|
|
<varlistentry>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>spi_exec</function> <literal>?-count <replaceable>n</replaceable>? ?-array <replaceable>name</replaceable>? <replaceable>query</replaceable> ?<replaceable>loop-body</replaceable>?</literal></term>
|
2000-03-31 00:13:30 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Call parser/planner/optimizer/executor for query.
|
|
|
|
The optional -count value tells <function>spi_exec</function>
|
|
|
|
the maximum number of rows
|
|
|
|
to be processed by the query.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
If the query is
|
|
|
|
a SELECT statement and the optional loop-body (a body of Tcl commands
|
|
|
|
like in a foreach statement) is given, it is evaluated for each
|
|
|
|
row selected and behaves like expected on continue/break. The values
|
|
|
|
of selected fields are put into variables named as the column names. So a
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
spi_exec "SELECT count(*) AS cnt FROM pg_proc"
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
will set the variable $cnt to the number of rows in the pg_proc system
|
|
|
|
catalog. If the option -array is given, the column values are stored
|
|
|
|
in the associative array named 'name' indexed by the column name
|
|
|
|
instead of individual variables.
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
spi_exec -array C "SELECT * FROM pg_class" {
|
|
|
|
elog DEBUG "have table $C(relname)"
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
will print a DEBUG log message for every row of pg_class. The return value
|
|
|
|
of <function>spi_exec</function> is the number of rows
|
2000-08-25 17:17:50 +02:00
|
|
|
affected by the query as found in
|
2000-03-31 00:13:30 +02:00
|
|
|
the global variable SPI_processed.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>spi_prepare</function> <replaceable>query</replaceable> <replaceable>typelist</replaceable></term>
|
2000-03-31 00:13:30 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Prepares AND SAVES a query plan for later execution. It is a bit different
|
|
|
|
from the C level SPI_prepare in that the plan is automatically copied to the
|
2001-09-10 23:58:47 +02:00
|
|
|
top-level memory context. Thus, there is currently no way of preparing a
|
2000-03-31 00:13:30 +02:00
|
|
|
plan without saving it.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
If the query references arguments, the type names must be given as a Tcl
|
2001-09-10 23:58:47 +02:00
|
|
|
list. The return value from <function>spi_prepare</function> is a query ID to be used in
|
|
|
|
subsequent calls to <function>spi_execp</function>. See <function>spi_execp</function> for a sample.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
2001-09-10 23:58:47 +02:00
|
|
|
<term><function>spi_exec</> <literal>?-count <replaceable>n</replaceable>? ?-array<replaceable>name</replaceable>? ?-nulls<replaceable>string</replaceable>? <replaceable>queryid</replaceable> ?<replaceable>value-list</replaceable>? ?<replaceable>loop-body</replaceable>?</literal></term>
|
2000-03-31 00:13:30 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
Execute a prepared plan from <function>spi_prepare</> with variable substitution.
|
|
|
|
The optional <literal>-count</literal> value tells <function>spi_execp</> the maximum number of rows
|
2000-03-31 00:13:30 +02:00
|
|
|
to be processed by the query.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
The optional value for <literal>-nulls</> is a string of spaces and 'n' characters
|
|
|
|
telling <function>spi_execp</function> which of the values are NULL's. If given, it must
|
2000-03-31 00:13:30 +02:00
|
|
|
have exactly the length of the number of values.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
The <parameter>queryid</> is the ID returned by the <function>spi_prepare</function> call.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
If there was a <parameter>typelist</> given to <function>spi_prepare</function>, a Tcl list of values of
|
2000-03-31 00:13:30 +02:00
|
|
|
exactly the same length must be given to spi_execp after the query. If
|
|
|
|
the type list on spi_prepare was empty, this argument must be omitted.
|
|
|
|
</para>
|
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
If the query is a SELECT statement, the same as described for <function>spi_exec</>
|
2000-03-31 00:13:30 +02:00
|
|
|
happens for the loop-body and the variables for the fields selected.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
Here's an example for a PL/Tcl function using a prepared plan:
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS '
|
|
|
|
if {![ info exists GD(plan) ]} {
|
|
|
|
# prepare the saved plan on the first call
|
|
|
|
set GD(plan) [ spi_prepare \\
|
|
|
|
"SELECT count(*) AS cnt FROM t1 WHERE num >= \\$1 AND num <= \\$2" \\
|
|
|
|
int4 ]
|
|
|
|
}
|
|
|
|
spi_execp -count 1 $GD(plan) [ list $1 $2 ]
|
|
|
|
return $cnt
|
|
|
|
' LANGUAGE 'pltcl';
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Note that each backslash that Tcl should see must be doubled in
|
|
|
|
the query creating the function, since the main parser processes
|
|
|
|
backslashes too on CREATE FUNCTION.
|
2001-09-10 23:58:47 +02:00
|
|
|
Inside the query string given to <function>spi_prepare</> should
|
2000-03-31 00:13:30 +02:00
|
|
|
really be dollar signs to mark the parameter positions and to not let
|
|
|
|
$1 be substituted by the value given in the first function call.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
2001-10-13 06:23:50 +02:00
|
|
|
|
|
|
|
</variablelist>
|
|
|
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title> Modules and the <function>unknown</> command</title>
|
2000-03-31 00:13:30 +02:00
|
|
|
<para>
|
2001-09-10 23:58:47 +02:00
|
|
|
PL/Tcl has a special support for things often used. It
|
|
|
|
recognizes two magic tables, <literal>pltcl_modules</> and
|
|
|
|
<literal>pltcl_modfuncs</>. If these exist, the module
|
|
|
|
'unknown' is loaded into the interpreter right after
|
|
|
|
creation. Whenever an unknown Tcl procedure is called, the
|
|
|
|
unknown proc is asked to check if the procedure is defined in
|
|
|
|
one of the modules. If this is true, the module is loaded on
|
2001-10-13 06:23:50 +02:00
|
|
|
demand.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
<para>
|
2001-10-13 06:23:50 +02:00
|
|
|
There are support scripts to maintain these tables:
|
|
|
|
<command>pltcl_loadmod</>,<command>pltcl_listmod</>,
|
|
|
|
<command>pltcl_delmod</> and source for the
|
|
|
|
unknown module <filename>share/unknown.pltcl</> that must be loaded
|
|
|
|
into database initially for getting unknown support.
|
2000-03-31 00:13:30 +02:00
|
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
|
|
Local variables:
|
|
|
|
mode:sgml
|
|
|
|
sgml-omittag:nil
|
|
|
|
sgml-shorttag:t
|
|
|
|
sgml-minimize-attributes:nil
|
|
|
|
sgml-always-quote-attributes:t
|
|
|
|
sgml-indent-step:1
|
|
|
|
sgml-indent-data:t
|
|
|
|
sgml-parent-document:nil
|
|
|
|
sgml-default-dtd-file:"./reference.ced"
|
|
|
|
sgml-exposed-tags:nil
|
2000-03-31 05:27:42 +02:00
|
|
|
sgml-local-catalogs:("/usr/lib/sgml/catalog")
|
2000-03-31 00:13:30 +02:00
|
|
|
sgml-local-ecat-files:nil
|
|
|
|
End:
|
|
|
|
-->
|