Commit 883ac5ca authored by Tom Lane's avatar Tom Lane

More minor updates and copy-editing.

parent 1fbdb6bc
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/plhandler.sgml,v 1.2 2003/11/29 19:51:37 pgsql Exp $ $PostgreSQL: pgsql/doc/src/sgml/plhandler.sgml,v 1.3 2004/12/30 21:45:36 tgl Exp $
--> -->
<chapter id="plhandler"> <chapter id="plhandler">
...@@ -154,6 +154,12 @@ CREATE LANGUAGE plsample ...@@ -154,6 +154,12 @@ CREATE LANGUAGE plsample
</programlisting> </programlisting>
</para> </para>
<para>
The procedural languages included in the standard distribution
are good references when trying to write your own call handler.
Look into the <filename>src/pl</> subdirectory of the source tree.
</para>
</chapter> </chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.34 2004/12/13 18:05:08 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.35 2004/12/30 21:45:36 tgl Exp $
--> -->
<chapter id="plperl"> <chapter id="plperl">
...@@ -132,9 +132,66 @@ CREATE FUNCTION empcomp(employee) RETURNS integer AS $$ ...@@ -132,9 +132,66 @@ CREATE FUNCTION empcomp(employee) RETURNS integer AS $$
return $emp-&gt;{basesalary} + $emp-&gt;{bonus}; return $emp-&gt;{basesalary} + $emp-&gt;{bonus};
$$ LANGUAGE plperl; $$ LANGUAGE plperl;
SELECT name, empcomp(employee) FROM employee; SELECT name, empcomp(employee.*) FROM employee;
</programlisting> </programlisting>
</para> </para>
<para>
A PL/Perl function can return a composite-type result using the same
approach: return a reference to a hash that has the required attributes.
For example,
<programlisting>
CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
return {f2 =&gt; 'hello', f1 =&gt; 1, f3 =&gt; 'world'};
$$ LANGUAGE plperl;
SELECT * FROM perl_row();
</programlisting>
Any columns in the declared result data type that are not present in the
hash will be returned as NULLs.
</para>
<para>
PL/Perl functions can also return sets of either scalar or composite
types. To do this, return a reference to an array that contains
either scalars or references to hashes, respectively. Here are
some simple examples:
<programlisting>
CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
return [0..$_[0]];
$$ LANGUAGE plperl;
SELECT * FROM perl_set_int(5);
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
return [
{ f1 =&gt; 1, f2 =&gt; 'Hello', f3 =&gt; 'World' },
{ f1 =&gt; 2, f2 =&gt; 'Hello', f3 =&gt; 'PostgreSQL' },
{ f1 =&gt; 3, f2 =&gt; 'Hello', f3 =&gt; 'PL/Perl' }
];
$$ LANGUAGE plperl;
SELECT * FROM perl_set();
</programlisting>
Note that when you do this, Perl will have to build the entire array in
memory; therefore the technique does not scale to very large result sets.
</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>
</sect1> </sect1>
<sect1 id="plperl-database"> <sect1 id="plperl-database">
...@@ -202,6 +259,37 @@ $res = $rv-&gt;{status}; ...@@ -202,6 +259,37 @@ $res = $rv-&gt;{status};
To get the number of rows affected, do: To get the number of rows affected, do:
<programlisting> <programlisting>
$nrows = $rv-&gt;{processed}; $nrows = $rv-&gt;{processed};
</programlisting>
</para>
<para>
Here is a complete example:
<programlisting>
CREATE TABLE test (
i int,
v varchar
);
INSERT INTO test (i, v) VALUES (1, 'first line');
INSERT INTO test (i, v) VALUES (2, 'second line');
INSERT INTO test (i, v) VALUES (3, 'third line');
INSERT INTO test (i, v) VALUES (4, 'immortal');
CREATE FUNCTION test_munge() RETURNS SETOF test AS $$
my $res = [];
my $rv = spi_exec_query('select i, v from test;');
my $status = $rv-&gt;{status};
my $nrows = $rv-&gt;{processed};
foreach my $rn (0 .. $nrows - 1) {
my $row = $rv-&gt;{rows}[$rn];
$row-&gt;{i} += 200 if defined($row-&gt;{i});
$row-&gt;{v} =~ tr/A-Za-z/a-zA-Z/ if (defined($row-&gt;{v}));
push @$res, $row;
}
return $res;
$$ LANGUAGE plperl;
SELECT * FROM test_munge();
</programlisting> </programlisting>
</para> </para>
</listitem> </listitem>
...@@ -224,8 +312,14 @@ $nrows = $rv-&gt;{processed}; ...@@ -224,8 +312,14 @@ $nrows = $rv-&gt;{processed};
Perl code, the error propagates out to the calling query, causing Perl code, the error propagates out to the calling query, causing
the current transaction or subtransaction to be aborted. This the current transaction or subtransaction to be aborted. This
is effectively the same as the Perl <literal>die</> command. is effectively the same as the Perl <literal>die</> command.
The other levels simply report the message to the system log The other levels only generate messages of different
and/or client. priority levels.
Whether messages of a particular priority are reported to the client,
written to the server log, or both is controlled by the
<xref linkend="guc-log-min-messages"> and
<xref linkend="guc-client-min-messages"> configuration
variables. See <xref linkend="runtime-config"> for more
information.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -242,72 +336,8 @@ $nrows = $rv-&gt;{processed}; ...@@ -242,72 +336,8 @@ $nrows = $rv-&gt;{processed};
had been displayed by a <command>SELECT</command> statement). had been displayed by a <command>SELECT</command> statement).
Conversely, the <literal>return</> command will accept any string Conversely, the <literal>return</> command will accept any string
that is acceptable input format for the function's declared return that is acceptable input format for the function's declared return
type. So, the PL/Perl programmer can manipulate data values as if type. So, within the PL/Perl function,
they were just text. all values are just text strings.
</para>
<para>
PL/Perl can also return row sets and composite types, and row sets
of composite types. Here is an example of a PL/Perl function
returning a row set of a row type. Note that a composite type is
always represented as a hash reference.
<programlisting>
CREATE TABLE test (
i int,
v varchar
);
INSERT INTO test (i, v) VALUES (1, 'first line');
INSERT INTO test (i, v) VALUES (2, 'second line');
INSERT INTO test (i, v) VALUES (3, 'third line');
INSERT INTO test (i, v) VALUES (4, 'immortal');
CREATE FUNCTION test_munge() RETURNS SETOF test AS $$
my $res = [];
my $rv = spi_exec_query('select i, v from test;');
my $status = $rv-&gt;{status};
my $nrows = $rv-&gt;{processed};
foreach my $rn (0 .. $nrows - 1) {
my $row = $rv-&gt;{rows}[$rn];
$row-&gt;{i} += 200 if defined($row-&gt;{i});
$row-&gt;{v} =~ tr/A-Za-z/a-zA-Z/ if (defined($row-&gt;{v}));
push @$res, $row;
}
return $res;
$$ LANGUAGE plperl;
SELECT * FROM test_munge();
</programlisting>
</para>
<para>
Here is an example of a PL/Perl function returning a composite
type:
<programlisting>
CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
return {f2 =&gt; 'hello', f1 =&gt; 1, f3 =&gt; 'world'};
$$ LANGUAGE plperl;
</programlisting>
</para>
<para>
Here is an example of a PL/Perl function returning a row set of a
composite type. Since a row set is always a reference to an array
and a composite type is always a reference to a hash, a row set of a
composite type is a reference to an array of hash references.
<programlisting>
CREATE TYPE testsetperl AS (f1 integer, f2 text, f3 text);
CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testsetperl AS $$
return [
{ f1 =&gt; 1, f2 =&gt; 'Hello', f3 =&gt; 'World' },
{ f1 =&gt; 2, f2 =&gt; 'Hello', f3 =&gt; 'PostgreSQL' },
{ f1 =&gt; 3, f2 =&gt; 'Hello', f3 =&gt; 'PL/Perl' }
];
$$ LANGUAGE plperl;
</programlisting>
</para> </para>
</sect1> </sect1>
...@@ -317,8 +347,7 @@ $$ LANGUAGE plperl; ...@@ -317,8 +347,7 @@ $$ LANGUAGE plperl;
<para> <para>
You can use the global hash <varname>%_SHARED</varname> to store You can use the global hash <varname>%_SHARED</varname> to store
data, including code references, between function calls for the data, including code references, between function calls for the
lifetime of the current session, which is bounded from below by lifetime of the current session.
the lifetime of the current transaction.
</para> </para>
<para> <para>
...@@ -360,12 +389,12 @@ SELECT myfuncs(); /* initializes the function */ ...@@ -360,12 +389,12 @@ SELECT myfuncs(); /* initializes the function */
CREATE OR REPLACE FUNCTION use_quote(TEXT) RETURNS text AS $$ CREATE OR REPLACE FUNCTION use_quote(TEXT) RETURNS text AS $$
my $text_to_quote = shift; my $text_to_quote = shift;
my $qfunc = $_SHARED{myquote}; my $qfunc = $_SHARED{myquote};
return &$qfunc($text_to_quote); return &amp;$qfunc($text_to_quote);
$$ LANGUAGE plperl; $$ LANGUAGE plperl;
</programlisting> </programlisting>
(You could have replaced the above with the one-liner (You could have replaced the above with the one-liner
<literal>return $_SHARED{myquote}->($_[0]);</literal> <literal>return $_SHARED{myquote}-&gt;($_[0]);</literal>
at the expense of readability.) at the expense of readability.)
</para> </para>
</sect1> </sect1>
...@@ -619,9 +648,7 @@ CREATE TRIGGER test_valid_id_trig ...@@ -619,9 +648,7 @@ CREATE TRIGGER test_valid_id_trig
<para> <para>
In the current implementation, if you are fetching or returning In the current implementation, if you are fetching or returning
very large data sets, you should be aware that these will all go very large data sets, you should be aware that these will all go
into memory. Future features will help with this. In the into memory.
meantime, we suggest that you not use PL/Perl if you will fetch
or return very large result sets.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
......
This diff is collapsed.
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.25 2004/12/17 02:14:44 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.26 2004/12/30 21:45:36 tgl Exp $ -->
<chapter id="plpython"> <chapter id="plpython">
<title>PL/Python - Python Procedural Language</title> <title>PL/Python - Python Procedural Language</title>
...@@ -46,15 +46,16 @@ ...@@ -46,15 +46,16 @@
<title>PL/Python Functions</title> <title>PL/Python Functions</title>
<para> <para>
The Python code you write gets transformed into a Python function. Functions in PL/Python are declared in the usual way, for example
For example,
<programlisting> <programlisting>
CREATE FUNCTION myfunc(text) RETURNS text CREATE FUNCTION myfunc(text) RETURNS text
AS 'return args[0]' AS 'return args[0]'
LANGUAGE plpythonu; LANGUAGE plpythonu;
</programlisting> </programlisting>
gets transformed into The Python code that is given as the body of the function definition
gets transformed into a Python function.
For example, the above results in
<programlisting> <programlisting>
def __plpython_procedure_myfunc_23456(): def __plpython_procedure_myfunc_23456():
...@@ -151,19 +152,23 @@ def __plpython_procedure_myfunc_23456(): ...@@ -151,19 +152,23 @@ def __plpython_procedure_myfunc_23456():
<literal>plpy.notice(<replaceable>msg</>)</literal>, <literal>plpy.notice(<replaceable>msg</>)</literal>,
<literal>plpy.warning(<replaceable>msg</>)</literal>, <literal>plpy.warning(<replaceable>msg</>)</literal>,
<literal>plpy.error(<replaceable>msg</>)</literal>, and <literal>plpy.error(<replaceable>msg</>)</literal>, and
<literal>plpy.fatal(<replaceable>msg</>)</literal>. <literal>plpy.fatal(<replaceable>msg</>)</literal>.<indexterm><primary>elog</><secondary>in PL/Python</></indexterm>
These are mostly equivalent to calling <function>plpy.error</function> and
<literal>elog(<replaceable>level</>, <replaceable>msg</>)</literal>
from C code.<indexterm><primary>elog</><secondary>in
PL/Python</></indexterm> <function>plpy.error</function> and
<function>plpy.fatal</function> actually raise a Python exception <function>plpy.fatal</function> actually raise a Python exception
which, if uncaught, causes the PL/Python module to call which, if uncaught, propagates out to the calling query, causing
<literal>elog(ERROR, msg)</literal> when the function handler the current transaction or subtransaction to be aborted.
returns from the Python interpreter. <literal>raise <literal>raise plpy.ERROR(<replaceable>msg</>)</literal> and
plpy.ERROR(<replaceable>msg</>)</literal> and <literal>raise <literal>raise plpy.FATAL(<replaceable>msg</>)</literal> are
plpy.FATAL(<replaceable>msg</>)</literal> are equivalent to calling equivalent to calling
<function>plpy.error</function> and <function>plpy.error</function> and
<function>plpy.fatal</function>, respectively. <function>plpy.fatal</function>, respectively.
The other functions only generate messages of different
priority levels.
Whether messages of a particular priority are reported to the client,
written to the server log, or both is controlled by the
<xref linkend="guc-log-min-messages"> and
<xref linkend="guc-client-min-messages"> configuration
variables. See <xref linkend="runtime-config"> for more information.
</para> </para>
<para> <para>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.33 2004/12/30 21:45:37 tgl Exp $
--> -->
<chapter id="pltcl"> <chapter id="pltcl">
...@@ -16,7 +16,8 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $ ...@@ -16,7 +16,8 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $
<para> <para>
PL/Tcl is a loadable procedural language for the PL/Tcl is a loadable procedural language for the
<productname>PostgreSQL</productname> database system <productname>PostgreSQL</productname> database system
that enables the Tcl language to be used to write functions and that enables the <ulink url="http://www.tcl.tk/">Tcl</ulink>
language to be used to write functions and
trigger procedures. trigger procedures.
</para> </para>
...@@ -59,7 +60,7 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $ ...@@ -59,7 +60,7 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $
The shared object for the <application>PL/Tcl</> and <application>PL/TclU</> call handlers is The shared object for the <application>PL/Tcl</> and <application>PL/TclU</> call handlers is
automatically built and installed in the automatically built and installed in the
<productname>PostgreSQL</productname> <productname>PostgreSQL</productname>
library directory if Tcl/Tk support is specified library directory if Tcl support is specified
in the configuration step of the installation procedure. To install in the configuration step of the installation procedure. To install
<application>PL/Tcl</> and/or <application>PL/TclU</> in a particular database, use the <application>PL/Tcl</> and/or <application>PL/TclU</> in a particular database, use the
<command>createlang</command> program, for example <command>createlang</command> program, for example
...@@ -77,8 +78,7 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $ ...@@ -77,8 +78,7 @@ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.32 2004/11/21 21:17:02 tgl Exp $
To create a function in the <application>PL/Tcl</> language, use the standard syntax: To create a function in the <application>PL/Tcl</> language, use the standard syntax:
<programlisting> <programlisting>
CREATE FUNCTION <replaceable>funcname</replaceable> CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-types</replaceable>) RETURNS <replaceable>return-type</replaceable> AS $$
(<replaceable>argument-types</replaceable>) RETURNS <replaceable>return-type</replaceable> AS $$
# PL/Tcl function body # PL/Tcl function body
$$ LANGUAGE pltcl; $$ LANGUAGE pltcl;
</programlisting> </programlisting>
...@@ -169,7 +169,16 @@ $$ LANGUAGE pltcl; ...@@ -169,7 +169,16 @@ $$ LANGUAGE pltcl;
<para> <para>
There is currently no support for returning a composite-type There is currently no support for returning a composite-type
result value. result value, nor for returning sets.
</para>
<para>
<application>PL/Tcl</> 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/Tcl</> function
as returning a domain type.
</para> </para>
</sect1> </sect1>
...@@ -180,10 +189,11 @@ $$ LANGUAGE pltcl; ...@@ -180,10 +189,11 @@ $$ LANGUAGE pltcl;
<para> <para>
The argument values supplied to a PL/Tcl function's code are simply The argument values supplied to a PL/Tcl function's code are simply
the input arguments converted to text form (just as if they had been the input arguments converted to text form (just as if they had been
displayed by a <command>SELECT</> statement). Conversely, the <literal>return</> displayed by a <command>SELECT</> statement). Conversely, the
<literal>return</>
command will accept any string that is acceptable input format for command will accept any string that is acceptable input format for
the function's declared return type. So, the PL/Tcl programmer can the function's declared return type. So, within the PL/Tcl function,
manipulate data values as if they were just text. all values are just text strings.
</para> </para>
</sect1> </sect1>
...@@ -215,9 +225,9 @@ $$ LANGUAGE pltcl; ...@@ -215,9 +225,9 @@ $$ LANGUAGE pltcl;
command. The global name of this variable is the function's internal command. The global name of this variable is the function's internal
name, and the local name is <literal>GD</>. It is recommended that name, and the local name is <literal>GD</>. It is recommended that
<literal>GD</> be used <literal>GD</> be used
for private data of a function. Use regular Tcl global variables for persistent private data of a function. Use regular Tcl global
only for values that you specifically intend to be shared among multiple variables only for values that you specifically intend to be shared among
functions. multiple functions.
</para> </para>
<para> <para>
...@@ -452,8 +462,7 @@ SELECT 'doesn''t' AS ret ...@@ -452,8 +462,7 @@ SELECT 'doesn''t' AS ret
Emits a log or error message. Possible levels are Emits a log or error message. Possible levels are
<literal>DEBUG</>, <literal>LOG</>, <literal>INFO</>, <literal>DEBUG</>, <literal>LOG</>, <literal>INFO</>,
<literal>NOTICE</>, <literal>WARNING</>, <literal>ERROR</>, and <literal>NOTICE</>, <literal>WARNING</>, <literal>ERROR</>, and
<literal>FATAL</>. Most simply emit the given message just like <literal>FATAL</>. <literal>ERROR</>
the <literal>elog</> C function. <literal>ERROR</>
raises an error condition; if this is not trapped by the surrounding raises an error condition; if this is not trapped by the surrounding
Tcl code, the error propagates out to the calling query, causing Tcl code, the error propagates out to the calling query, causing
the current transaction or subtransaction to be aborted. This the current transaction or subtransaction to be aborted. This
...@@ -461,7 +470,14 @@ SELECT 'doesn''t' AS ret ...@@ -461,7 +470,14 @@ SELECT 'doesn''t' AS ret
<literal>FATAL</> aborts the transaction and causes the current <literal>FATAL</> aborts the transaction and causes the current
session to shut down. (There is probably no good reason to use session to shut down. (There is probably no good reason to use
this error level in PL/Tcl functions, but it's provided for this error level in PL/Tcl functions, but it's provided for
completeness.) completeness.) The other levels only generate messages of different
priority levels.
Whether messages of a particular priority are reported to the client,
written to the server log, or both is controlled by the
<xref linkend="guc-log-min-messages"> and
<xref linkend="guc-client-min-messages"> configuration
variables. See <xref linkend="runtime-config"> for more
information.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
This diff is collapsed.
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.91 2004/12/30 03:13:56 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.92 2004/12/30 21:45:37 tgl Exp $
--> -->
<sect1 id="xfunc"> <sect1 id="xfunc">
...@@ -823,23 +823,15 @@ CREATE FUNCTION test(int, int) RETURNS int ...@@ -823,23 +823,15 @@ CREATE FUNCTION test(int, int) RETURNS int
<title>Procedural Language Functions</title> <title>Procedural Language Functions</title>
<para> <para>
<productname>PostgreSQL</productname> allows user-defined functions
to be written in other languages besides SQL and C. These other
languages are generically called <firstterm>procedural
languages</firstterm> (<acronym>PL</>s).
Procedural languages aren't built into the Procedural languages aren't built into the
<productname>PostgreSQL</productname> server; they are offered <productname>PostgreSQL</productname> server; they are offered
by loadable modules. Please refer to the documentation of the by loadable modules.
procedural language in question for details about the syntax and how the See <xref linkend="xplang"> and following chapters for more
function body is interpreted for each language. information.
</para>
<para>
There are currently four procedural languages available in the
standard <productname>PostgreSQL</productname> distribution:
<application>PL/pgSQL</application>, <application>PL/Tcl</application>,
<application>PL/Perl</application>, and
<application>PL/Python</application>.
Refer to <xref linkend="xplang"> for more information.
Other languages can be defined by users.
The basics of developing a new procedural language are covered in <xref
linkend="plhandler">.
</para> </para>
</sect1> </sect1>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.27 2004/12/30 03:13:56 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.28 2004/12/30 21:45:37 tgl Exp $
--> -->
<chapter id="xplang"> <chapter id="xplang">
...@@ -10,27 +10,32 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.27 2004/12/30 03:13:56 tgl Exp $ ...@@ -10,27 +10,32 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.27 2004/12/30 03:13:56 tgl Exp $
</indexterm> </indexterm>
<para> <para>
<productname>PostgreSQL</productname> allows users to add new <productname>PostgreSQL</productname> allows user-defined functions
programming languages to be available for writing functions and to be written in other languages besides SQL and C. These other
procedures. These are called <firstterm>procedural languages are generically called <firstterm>procedural
languages</firstterm> (PL). In the case of a function or trigger languages</firstterm> (<acronym>PL</>s). For a function
procedure written in a procedural language, the database server has written in a procedural language, the database server has
no built-in knowledge about how to interpret the function's source no built-in knowledge about how to interpret the function's source
text. Instead, the task is passed to a special handler that knows text. Instead, the task is passed to a special handler that knows
the details of the language. The handler could either do all the the details of the language. The handler could either do all the
work of parsing, syntax analysis, execution, etc. itself, or it work of parsing, syntax analysis, execution, etc. itself, or it
could serve as <quote>glue</quote> between could serve as <quote>glue</quote> between
<productname>PostgreSQL</productname> and an existing implementation <productname>PostgreSQL</productname> and an existing implementation
of a programming language. The handler itself is a special of a programming language. The handler itself is a
C language function compiled into a shared object and C language function compiled into a shared object and
loaded on demand. loaded on demand, just like any other C function.
</para> </para>
<para> <para>
Writing a handler for a new procedural language is described in There are currently four procedural languages available in the
<xref linkend="plhandler">. Several procedural languages are standard <productname>PostgreSQL</productname> distribution:
available in the core <productname>PostgreSQL</productname> <application>PL/pgSQL</application> (<xref linkend="plpgsql">),
distribution, which can serve as examples. <application>PL/Tcl</application> (<xref linkend="pltcl">),
<application>PL/Perl</application> (<xref linkend="plperl">), and
<application>PL/Python</application> (<xref linkend="plpython">).
Other languages can be defined by users.
The basics of developing a new procedural language are covered in <xref
linkend="plhandler">.
</para> </para>
<para> <para>
...@@ -46,14 +51,16 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.27 2004/12/30 03:13:56 tgl Exp $ ...@@ -46,14 +51,16 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.27 2004/12/30 03:13:56 tgl Exp $
A procedural language must be <quote>installed</quote> into each A procedural language must be <quote>installed</quote> into each
database where it is to be used. But procedural languages installed in database where it is to be used. But procedural languages installed in
the database <literal>template1</> are automatically available in all the database <literal>template1</> are automatically available in all
subsequently created databases. So the database administrator can subsequently created databases, since their entries in
<literal>template1</> will be copied by <command>CREATE DATABASE</>.
So the database administrator can
decide which languages are available in which databases and can make decide which languages are available in which databases and can make
some languages available by default if he chooses. some languages available by default if he chooses.
</para> </para>
<para> <para>
For the languages supplied with the standard distribution, the For the languages supplied with the standard distribution, the
program <command>createlang</command> may be used to install the program <xref linkend="app-createlang"> may be used to install the
language instead of carrying out the details by hand. For language instead of carrying out the details by hand. For
example, to install the language example, to install the language
<application>PL/pgSQL</application> into the database <application>PL/pgSQL</application> into the database
...@@ -72,23 +79,24 @@ createlang plpgsql template1 ...@@ -72,23 +79,24 @@ createlang plpgsql template1
</title> </title>
<para> <para>
A procedural language is installed in a database in three steps, A procedural language is installed in a database in four steps,
which must be carried out by a database superuser. The which must be carried out by a database superuser. The
<command>createlang</command> program automates <xref <command>createlang</command> program automates all but <xref
linkend="xplang-install-cr1"> and <xref linkend="xplang-install-cr1">.
linkend="xplang-install-cr2">.
</para> </para>
<step performance="required"> <step performance="required" id="xplang-install-cr1">
<para> <para>
The shared object for the language handler must be compiled and The shared object for the language handler must be compiled and
installed into an appropriate library directory. This works in the same installed into an appropriate library directory. This works in the same
way as building and installing modules with regular user-defined C way as building and installing modules with regular user-defined C
functions does; see <xref linkend="dfunc">. functions does; see <xref linkend="dfunc">. Often, the language
handler will depend on an external library that provides the actual
programming language engine; if so, that must be installed as well.
</para> </para>
</step> </step>
<step performance="required" id="xplang-install-cr1"> <step performance="required" id="xplang-install-cr2">
<para> <para>
The handler must be declared with the command The handler must be declared with the command
<synopsis> <synopsis>
...@@ -104,12 +112,29 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable>() ...@@ -104,12 +112,29 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable>()
</para> </para>
</step> </step>
<step performance="required" id="xplang-install-cr2"> <step performance="optional" id="xplang-install-cr3">
<para>
Optionally, the language handler may provide a <quote>validator</>
function that checks a function definition for correctness without
actually executing it. The validator function is called by
<command>CREATE FUNCTION</> if it exists. If a validator function
is provided by the handler, declare it with a command like
<synopsis>
CREATE FUNCTION <replaceable>validator_function_name</replaceable>(oid)
RETURNS void
AS '<replaceable>path-to-shared-object</replaceable>'
LANGUAGE C;
</synopsis>
</para>
</step>
<step performance="required" id="xplang-install-cr4">
<para> <para>
The PL must be declared with the command The PL must be declared with the command
<synopsis> <synopsis>
CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable> CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable>
HANDLER <replaceable>handler_function_name</replaceable>; HANDLER <replaceable>handler_function_name</replaceable>
<optional>VALIDATOR <replaceable>validator_function_name</replaceable></optional> ;
</synopsis> </synopsis>
The optional key word <literal>TRUSTED</literal> specifies that The optional key word <literal>TRUSTED</literal> specifies that
ordinary database users that have no superuser privileges should ordinary database users that have no superuser privileges should
...@@ -150,13 +175,24 @@ CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS ...@@ -150,13 +175,24 @@ CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS
</programlisting> </programlisting>
</para> </para>
<para>
<application>PL/pgSQL</application> has a validator function,
so we declare that too:
<programlisting>
CREATE FUNCTION plpgsql_validator(oid) RETURNS void AS
'$libdir/plpgsql' LANGUAGE C;
</programlisting>
</para>
<para> <para>
The command The command
<programlisting> <programlisting>
CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
HANDLER plpgsql_call_handler; HANDLER plpgsql_call_handler
VALIDATOR plpgsql_validator;
</programlisting> </programlisting>
then defines that the previously declared call handler function then defines that the previously declared functions
should be invoked for functions and trigger procedures where the should be invoked for functions and trigger procedures where the
language attribute is <literal>plpgsql</literal>. language attribute is <literal>plpgsql</literal>.
</para> </para>
...@@ -166,7 +202,7 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql ...@@ -166,7 +202,7 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
In a default <productname>PostgreSQL</productname> installation, In a default <productname>PostgreSQL</productname> installation,
the handler for the <application>PL/pgSQL</application> language the handler for the <application>PL/pgSQL</application> language
is built and installed into the <quote>library</quote> is built and installed into the <quote>library</quote>
directory. If <application>Tcl/Tk</> support is configured in, the handlers for directory. If <application>Tcl</> support is configured in, the handlers for
<application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same <application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same
location. Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built location. Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built
and installed if Perl support is configured, and <application>PL/PythonU</> is and installed if Perl support is configured, and <application>PL/PythonU</> is
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment