Move the "how to write a PL call handler" parts from the CREATE LANGUAGE
man page to the Programmer's Guide.
This commit is contained in:
parent
f25ed23c57
commit
22ae53d4cd
@ -1,66 +1,98 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.16 2001/09/03 12:57:49 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.17 2001/09/06 10:28:39 petere Exp $
|
||||||
Postgres documentation
|
Postgres documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<refentry id="SQL-CREATELANGUAGE">
|
<refentry id="SQL-CREATELANGUAGE">
|
||||||
|
<docinfo>
|
||||||
|
<date>2001-09-05</date>
|
||||||
|
</docinfo>
|
||||||
|
|
||||||
<refmeta>
|
<refmeta>
|
||||||
<refentrytitle id="sql-createlanguage-title">
|
<refentrytitle id="sql-createlanguage-title">CREATE LANGUAGE</refentrytitle>
|
||||||
CREATE LANGUAGE
|
|
||||||
</refentrytitle>
|
|
||||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||||
</refmeta>
|
</refmeta>
|
||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>
|
<refname>CREATE LANGUAGE</refname>
|
||||||
CREATE LANGUAGE
|
<refpurpose>define a new procedural language</refpurpose>
|
||||||
</refname>
|
|
||||||
<refpurpose>
|
|
||||||
define a new procedural language
|
|
||||||
</refpurpose>
|
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<refsynopsisdivinfo>
|
<synopsis>
|
||||||
<date>1999-07-20</date>
|
|
||||||
</refsynopsisdivinfo>
|
|
||||||
<synopsis>
|
|
||||||
CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langname</replaceable>
|
CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langname</replaceable>
|
||||||
HANDLER <replaceable class="parameter">call_handler</replaceable>
|
HANDLER <replaceable class="parameter">call_handler</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1 id="sql-createlanguage-description">
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATELANGUAGE-1">
|
|
||||||
<refsect2info>
|
|
||||||
<date>1998-09-09</date>
|
|
||||||
</refsect2info>
|
|
||||||
<title>
|
|
||||||
Inputs
|
|
||||||
</title>
|
|
||||||
<para>
|
<para>
|
||||||
|
Using <command>CREATE LANGUAGE</command>, a
|
||||||
|
<productname>PostgreSQL</productname> user can register a new
|
||||||
|
procedural language with a <productname>PostgreSQL</productname>
|
||||||
|
database. Subsequently, functions and trigger procedures can be
|
||||||
|
defined in this new language. The user must have the
|
||||||
|
<productname>PostgreSQL</productname> superuser privilege to
|
||||||
|
register a new language.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>CREATE LANGUAGE</command> effectively associates the
|
||||||
|
language name with a call handler that is responsible for executing
|
||||||
|
functions written in the language. Refer to the
|
||||||
|
<citetitle>Programmer's Guide</citetitle> for more information
|
||||||
|
about language call handlers.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that procedural languages are local to individual databases.
|
||||||
|
To make a language available in all databases by default, it should
|
||||||
|
be installed into the <literal>template1</literal> database.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="sql-createlanguage-parameters">
|
||||||
|
<title>Parameters</title>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>TRUSTED</term>
|
<term><literal>TRUSTED</literal></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<function> TRUSTED</function> specifies that the call handler for
|
<literal>TRUSTED</literal> specifies that the call handler for
|
||||||
the language is safe; that is, it offers an unprivileged user
|
the language is safe, that is, it does not offer an
|
||||||
no functionality to bypass access restrictions. If
|
unprivileged user any functionality to bypass access
|
||||||
this keyword is omitted when registering the language,
|
restrictions. If this keyword is omitted when registering the
|
||||||
only users with the <productname>Postgres</productname>
|
language, only users with the
|
||||||
superuser privilege can use
|
<productname>PostgreSQL</productname> superuser privilege can
|
||||||
this language to create new functions.
|
use this language to create new functions.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>PROCEDURAL</literal></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is a noise word.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="parameter">langname</replaceable></term>
|
<term><replaceable class="parameter">langname</replaceable></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of the new procedural language.
|
The name of the new procedural language. The language name is
|
||||||
The language name is case insensitive. A procedural
|
case insensitive. A procedural language cannot override one of
|
||||||
language cannot override one of the built-in languages of
|
the built-in languages of <productname>PostgreSQL</productname>.
|
||||||
<productname>Postgres</productname>.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For backward compatibility, the name may be enclosed by single
|
For backward compatibility, the name may be enclosed by single
|
||||||
quotes.
|
quotes.
|
||||||
@ -69,184 +101,96 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langna
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>HANDLER <replaceable class="parameter">call_handler</replaceable></term>
|
<term><literal>HANDLER</literal> <replaceable class="parameter">call_handler</replaceable></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<replaceable class="parameter">call_handler</replaceable> is the name
|
<replaceable class="parameter">call_handler</replaceable> is
|
||||||
of a previously
|
the name of a previously registered function that will be
|
||||||
registered function that will be called to execute the PL
|
called to execute the procedural language functions. The call
|
||||||
procedures.
|
handler for a procedural language must be written in a compiled
|
||||||
|
language such as C with version 1 call convention and
|
||||||
|
registered with <productname>PostgreSQL</productname> as a
|
||||||
|
function taking no arguments and returning the
|
||||||
|
<type>opaque</type> type, a placeholder for unspecified or
|
||||||
|
undefined types.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</refsect1>
|
||||||
|
|
||||||
</refsect2>
|
<refsect1 id="sql-createlanguage-diagnostics">
|
||||||
|
<title>Diagnostics</title>
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATELANGUAGE-2">
|
<msgset>
|
||||||
<refsect2info>
|
<msgentry>
|
||||||
<date>1998-09-09</date>
|
<msg>
|
||||||
</refsect2info>
|
<msgmain>
|
||||||
<title>
|
<msgtext>
|
||||||
Outputs
|
<screen>
|
||||||
</title>
|
|
||||||
<para>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><computeroutput>
|
|
||||||
CREATE
|
CREATE
|
||||||
</computeroutput></term>
|
</screen>
|
||||||
<listitem>
|
</msgtext>
|
||||||
|
</msgmain>
|
||||||
|
</msg>
|
||||||
|
|
||||||
|
<msgexplan>
|
||||||
<para>
|
<para>
|
||||||
This message is returned if the language is successfully
|
This message is returned if the language is successfully
|
||||||
created.
|
created.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</msgexplan>
|
||||||
</varlistentry>
|
</msgentry>
|
||||||
<varlistentry>
|
|
||||||
<term><computeroutput>
|
<msgentry>
|
||||||
|
<msg>
|
||||||
|
<msgmain>
|
||||||
|
<msgtext>
|
||||||
|
<screen>
|
||||||
ERROR: PL handler function <replaceable class="parameter">funcname</replaceable>() doesn't exist
|
ERROR: PL handler function <replaceable class="parameter">funcname</replaceable>() doesn't exist
|
||||||
</computeroutput></term>
|
</screen>
|
||||||
<listitem>
|
</msgtext>
|
||||||
<para>
|
</msgmain>
|
||||||
This error is returned if the function
|
</msg>
|
||||||
<replaceable class="parameter">funcname</replaceable>()
|
|
||||||
is not found.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</refsect2>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1 id="R1-SQL-CREATELANGUAGE-1">
|
<msgexplan>
|
||||||
<refsect1info>
|
|
||||||
<date>1998-09-09</date>
|
|
||||||
</refsect1info>
|
|
||||||
<title>
|
|
||||||
Description
|
|
||||||
</title>
|
|
||||||
<para>
|
<para>
|
||||||
Using <command>CREATE LANGUAGE</command>, a
|
This error is returned if the function <replaceable
|
||||||
<productname>Postgres</productname> user can register
|
class="parameter">funcname</replaceable>() is not found.
|
||||||
a new language with <productname>Postgres</productname>.
|
|
||||||
Subsequently, functions and
|
|
||||||
trigger procedures can be defined in this new language.
|
|
||||||
The user must have the <productname>Postgres</productname>
|
|
||||||
superuser privilege to
|
|
||||||
register a new language.
|
|
||||||
</para>
|
</para>
|
||||||
|
</msgexplan>
|
||||||
|
</msgentry>
|
||||||
|
</msgset>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATELANGUAGE-3">
|
<refsect1 id="sql-createlanguage-notes">
|
||||||
<refsect2info>
|
<title>Notes</title>
|
||||||
<date>1998-09-09</date>
|
|
||||||
</refsect2info>
|
|
||||||
<title>
|
|
||||||
Writing PL handlers
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
In <productname>Postgres</productname> 7.1 and later, call handlers
|
|
||||||
must adhere to the "version 1" function manager interface, not the
|
|
||||||
old-style interface.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The call handler for a procedural language must be written
|
This command normally should not be executed directly by users.
|
||||||
in a compiled language such as C and registered with
|
For the procedural languages supplied in the
|
||||||
<productname>Postgres</productname> as a function taking
|
<productname>PostgreSQL</productname> distribution, the <xref
|
||||||
no arguments and returning the
|
linkend="app-createlang"> program should be used, which will also
|
||||||
<type>opaque</type> type, a placeholder for unspecified or undefined types.
|
install the correct call handler. (<command>createlang</command>
|
||||||
This prevents the call handler from being
|
will call <command>CREATE LANGUAGE</command> internally.)
|
||||||
called directly as a function from queries.
|
|
||||||
(However, arguments may be supplied in the actual call when a
|
|
||||||
PL function in the language offered by the handler is to be executed.)
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The call handler is called in the same way as any other
|
Use the <xref linkend="sql-createfunction"> command to create a new
|
||||||
function: it receives a pointer to a FunctionCallInfoData struct
|
function.
|
||||||
containing argument values and information about the called function,
|
|
||||||
and it is expected to return a Datum result (and possibly set the
|
|
||||||
<literal>isnull</literal> field of the FunctionCallInfoData struct,
|
|
||||||
if it wishes to return an SQL NULL result). The difference between
|
|
||||||
a call handler and an ordinary callee function is that the
|
|
||||||
<literal>flinfo->fn_oid</literal> field of the FunctionCallInfoData
|
|
||||||
struct will contain the OID of the PL function to be called, not of
|
|
||||||
the call handler itself. The call handler must use this field to
|
|
||||||
determine which function to execute. Also, the passed argument list
|
|
||||||
has been set up according to the declaration of the target PL function,
|
|
||||||
not of the call handler.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
It's up to the call handler to fetch the
|
Use <xref linkend="sql-droplanguage">, or better yet the <xref
|
||||||
<filename>pg_proc</filename> entry and
|
linkend="app-droplang"> program, to drop procedural languages.
|
||||||
to analyze the argument and return types of the called
|
|
||||||
procedure. The AS clause from the
|
|
||||||
<command>CREATE FUNCTION</command> of
|
|
||||||
the procedure will be found in the <literal>prosrc</literal>
|
|
||||||
attribute of the
|
|
||||||
<filename>pg_proc</filename> table entry. This may be the
|
|
||||||
source text in the procedural
|
|
||||||
language itself (like for PL/Tcl), a pathname to a
|
|
||||||
file, or anything else that tells the call handler what to
|
|
||||||
do in detail.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Often, the same function is called many times per SQL statement.
|
The system catalog <classname>pg_language</classname> records
|
||||||
A call handler can avoid repeated lookups of information about the
|
information about the currently installed procedural languages.
|
||||||
called function by using the <literal>flinfo->fn_extra</literal> field.
|
|
||||||
This will initially be NULL, but can be set by the call handler to
|
|
||||||
point at information about the PL function. On subsequent calls,
|
|
||||||
if <literal>flinfo->fn_extra</literal> is already non-NULL then it
|
|
||||||
can be used and the information lookup step skipped. The call handler
|
|
||||||
must be careful that <literal>flinfo->fn_extra</literal> is made to
|
|
||||||
point at memory that will live at least until the end of the current
|
|
||||||
query, since an FmgrInfo data structure could be kept that long.
|
|
||||||
One way to do this is to allocate the extra data in the memory context
|
|
||||||
specified by <literal>flinfo->fn_mcxt</literal>; such data will
|
|
||||||
normally have the same lifespan as the FmgrInfo itself. But the handler
|
|
||||||
could also choose to use a longer-lived context so that it can cache
|
|
||||||
function definition information across queries.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<screen>
|
||||||
When a PL function is invoked as a trigger, no explicit arguments
|
|
||||||
are passed, but the FunctionCallInfoData's
|
|
||||||
<literal>context</literal> field points at a TriggerData node,
|
|
||||||
rather than being NULL as it is in a plain function call.
|
|
||||||
A PL handler should provide mechanisms for PL functions to get
|
|
||||||
at the trigger information.
|
|
||||||
</para>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATELANGUAGE-4">
|
|
||||||
<refsect2info>
|
|
||||||
<date>1998-09-09</date>
|
|
||||||
</refsect2info>
|
|
||||||
<title>
|
|
||||||
Notes
|
|
||||||
</title>
|
|
||||||
<para>
|
|
||||||
Use <command>CREATE FUNCTION</command>
|
|
||||||
to create a function.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Use <command>DROP LANGUAGE</command> to drop procedural languages.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Refer to the table <filename>pg_language</filename>
|
|
||||||
for further information:
|
|
||||||
<programlisting>
|
|
||||||
<computeroutput>
|
|
||||||
Table "pg_language"
|
Table "pg_language"
|
||||||
Attribute | Type | Modifier
|
Attribute | Type | Modifier
|
||||||
---------------+---------+----------
|
---------------+---------+----------
|
||||||
@ -261,107 +205,61 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
|
|||||||
internal | f | f | 0 | n/a
|
internal | f | f | 0 | n/a
|
||||||
C | f | f | 0 | /bin/cc
|
C | f | f | 0 | /bin/cc
|
||||||
sql | f | f | 0 | postgres
|
sql | f | f | 0 | postgres
|
||||||
</computeroutput>
|
</screen>
|
||||||
</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The call handler for a procedural language must normally be written
|
At present, the definition of a procedural language cannot be
|
||||||
in C and registered as 'internal' or 'C' language, depending
|
changed once is has been created.
|
||||||
on whether it is linked into the backend or dynamically loaded.
|
|
||||||
The call handler cannot use the old-style 'C' function interface.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
At present, the definitions for a procedural language cannot be
|
|
||||||
changed once they have been created.
|
|
||||||
</para>
|
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="R1-SQL-CREATELANGUAGE-6">
|
<refsect1 id="sql-createlanguage-examples">
|
||||||
<title>
|
<title>Examples</title>
|
||||||
Usage
|
|
||||||
</title>
|
|
||||||
<para>
|
|
||||||
This is a template for a PL handler written in C:
|
|
||||||
<programlisting>
|
|
||||||
#include "executor/spi.h"
|
|
||||||
#include "commands/trigger.h"
|
|
||||||
#include "utils/elog.h"
|
|
||||||
#include "fmgr.h"
|
|
||||||
#include "access/heapam.h"
|
|
||||||
#include "utils/syscache.h"
|
|
||||||
#include "catalog/pg_proc.h"
|
|
||||||
#include "catalog/pg_type.h"
|
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(plsample_call_handler);
|
|
||||||
|
|
||||||
Datum
|
|
||||||
plsample_call_handler(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
Datum retval;
|
|
||||||
|
|
||||||
if (CALLED_AS_TRIGGER(fcinfo))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Called as a trigger procedure
|
|
||||||
*/
|
|
||||||
TriggerData *trigdata = (TriggerData *) fcinfo->context;
|
|
||||||
|
|
||||||
retval = ...
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Called as a function
|
|
||||||
*/
|
|
||||||
|
|
||||||
retval = ...
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Only a few thousand lines of code have to be added instead
|
The following two commands executed in sequence will register a new
|
||||||
of the dots to complete the PL call handler.
|
procedural language and the associated call handler.
|
||||||
See <command>CREATE FUNCTION</command> for information on how to compile
|
<programlisting>
|
||||||
it into a loadable module.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The following commands then register the sample procedural
|
|
||||||
language:
|
|
||||||
<programlisting>
|
|
||||||
CREATE FUNCTION plsample_call_handler () RETURNS opaque
|
CREATE FUNCTION plsample_call_handler () RETURNS opaque
|
||||||
AS '/usr/local/pgsql/lib/plsample.so'
|
AS '/usr/local/pgsql/lib/plsample.so'
|
||||||
LANGUAGE C;
|
LANGUAGE C;
|
||||||
CREATE LANGUAGE plsample
|
CREATE LANGUAGE plsample
|
||||||
HANDLER plsample_call_handler;
|
HANDLER plsample_call_handler;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="R1-SQL-CREATELANGUAGE-7">
|
<refsect1 id="sql-createlanguage-compat">
|
||||||
<title>
|
<title>Compatibility</title>
|
||||||
Compatibility
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATELANGUAGE-5">
|
|
||||||
<refsect2info>
|
|
||||||
<date>1998-09-09</date>
|
|
||||||
</refsect2info>
|
|
||||||
<title>
|
|
||||||
SQL92
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<command>CREATE LANGUAGE</command>
|
<command>CREATE LANGUAGE</command> is a
|
||||||
is a <productname>Postgres</productname> extension.
|
<productname>PostgreSQL</productname> extension.
|
||||||
There is no <command>CREATE LANGUAGE</command> statement in
|
</para>
|
||||||
<acronym>SQL92</acronym>.
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>History</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <command>CREATE LANGUAGE</command> command first appeared in
|
||||||
|
<productname>PostgreSQL</productname> 6.3.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See Also</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<simplelist type="inline">
|
||||||
|
<member><xref linkend="app-createlang"></member>
|
||||||
|
<member><xref linkend="sql-createfunction"></member>
|
||||||
|
<member><xref linkend="app-droplang"></member>
|
||||||
|
<member><xref linkend="sql-droplanguage"></member>
|
||||||
|
<member><citetitle>PostgreSQL Programmer's Guide</citetitle></member>
|
||||||
|
</simplelist>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.33 2001/08/28 14:20:26 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.34 2001/09/06 10:28:39 petere Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="xfunc">
|
<chapter id="xfunc">
|
||||||
@ -337,11 +337,11 @@ SELECT clean_EMP();
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There are currently three procedural languages available in the standard
|
There are currently four procedural languages available in the
|
||||||
<productname>Postgres</productname> distribution (PLSQL, PLTCL and
|
standard <productname>PostgreSQL</productname> distribution:
|
||||||
PLPERL), and other languages can be defined.
|
PL/pgSQL, PL/Tcl, PL/Perl, and PL/Python. Other languages can be
|
||||||
Refer to <xref linkend="xplang"> for
|
defined by users. Refer to <xref linkend="xplang"> for more
|
||||||
more information.
|
information.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
@ -1357,6 +1357,173 @@ LANGUAGE 'c';
|
|||||||
</sect3>
|
</sect3>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="xfunc-plhandler">
|
||||||
|
<title>Procedural Language Handlers</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
All calls to functions that are written in a language other than
|
||||||
|
the current <quote>version 1</quote> interface for compiled
|
||||||
|
languages, in particular in user-defined procedural languages, but
|
||||||
|
also functions written in SQL or the version 0 compiled language
|
||||||
|
interface, go through a <firstterm>call handler</firstterm>
|
||||||
|
function for the specific language. It is the responsibility of
|
||||||
|
the call handler to execute the function in a meaningful way, such
|
||||||
|
as by interpreting the supplied source text. This section
|
||||||
|
describes how a language call handler can be written. This is not
|
||||||
|
a common task, in fact, it has only been done a handful of times
|
||||||
|
in the history of <productname>PostgreSQL</productname>, but the
|
||||||
|
topic naturally belongs in this chapter, and the material might
|
||||||
|
give some insight into the extensible nature of the
|
||||||
|
<productname>PostgreSQL</productname> system.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The call handler for a procedural language is a
|
||||||
|
<quote>normal</quote> function, which must be written in a
|
||||||
|
compiled language such as C and registered with
|
||||||
|
<productname>PostgreSQL</productname> as taking no arguments and
|
||||||
|
returning the <type>opaque</type> type, a placeholder for
|
||||||
|
unspecified or undefined types. This prevents the call handler
|
||||||
|
from being called directly as a function from queries. (However,
|
||||||
|
arguments may be supplied in the actual call to the handler when a
|
||||||
|
function in the language offered by the handler is to be
|
||||||
|
executed.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
In <productname>PostgreSQL</productname> 7.1 and later, call
|
||||||
|
handlers must adhere to the <quote>version 1</quote> function
|
||||||
|
manager interface, not the old-style interface.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The call handler is called in the same way as any other function:
|
||||||
|
It receives a pointer to a
|
||||||
|
<structname>FunctionCallInfoData</structname> struct containing
|
||||||
|
argument values and information about the called function, and it
|
||||||
|
is expected to return a <type>Datum</type> result (and possibly
|
||||||
|
set the <structfield>isnull</structfield> field of the
|
||||||
|
<structname>FunctionCallInfoData</structname> struct, if it wishes
|
||||||
|
to return an SQL NULL result). The difference between a call
|
||||||
|
handler and an ordinary callee function is that the
|
||||||
|
<structfield>flinfo->fn_oid</structfield> field of the
|
||||||
|
<structname>FunctionCallInfoData</structname> struct will contain
|
||||||
|
the OID of the actual function to be called, not of the call
|
||||||
|
handler itself. The call handler must use this field to determine
|
||||||
|
which function to execute. Also, the passed argument list has
|
||||||
|
been set up according to the declaration of the target function,
|
||||||
|
not of the call handler.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
It's up to the call handler to fetch the
|
||||||
|
<classname>pg_proc</classname> entry and to analyze the argument
|
||||||
|
and return types of the called procedure. The AS clause from the
|
||||||
|
<command>CREATE FUNCTION</command> of the procedure will be found
|
||||||
|
in the <literal>prosrc</literal> attribute of the
|
||||||
|
<classname>pg_proc</classname> table entry. This may be the source
|
||||||
|
text in the procedural language itself (like for PL/Tcl), a
|
||||||
|
pathname to a file, or anything else that tells the call handler
|
||||||
|
what to do in detail.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Often, the same function is called many times per SQL statement.
|
||||||
|
A call handler can avoid repeated lookups of information about the
|
||||||
|
called function by using the
|
||||||
|
<structfield>flinfo->fn_extra</structfield> field. This will
|
||||||
|
initially be NULL, but can be set by the call handler to point at
|
||||||
|
information about the PL function. On subsequent calls, if
|
||||||
|
<structfield>flinfo->fn_extra</structfield> is already non-NULL
|
||||||
|
then it can be used and the information lookup step skipped. The
|
||||||
|
call handler must be careful that
|
||||||
|
<structfield>flinfo->fn_extra</structfield> is made to point at
|
||||||
|
memory that will live at least until the end of the current query,
|
||||||
|
since an <structname>FmgrInfo</structname> data structure could be
|
||||||
|
kept that long. One way to do this is to allocate the extra data
|
||||||
|
in the memory context specified by
|
||||||
|
<structfield>flinfo->fn_mcxt</structfield>; such data will
|
||||||
|
normally have the same lifespan as the
|
||||||
|
<structname>FmgrInfo</structname> itself. But the handler could
|
||||||
|
also choose to use a longer-lived context so that it can cache
|
||||||
|
function definition information across queries.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When a PL function is invoked as a trigger, no explicit arguments
|
||||||
|
are passed, but the
|
||||||
|
<structname>FunctionCallInfoData</structname>'s
|
||||||
|
<structfield>context</structfield> field points at a
|
||||||
|
<structname>TriggerData</structname> node, rather than being NULL
|
||||||
|
as it is in a plain function call. A language handler should
|
||||||
|
provide mechanisms for PL functions to get at the trigger
|
||||||
|
information.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This is a template for a PL handler written in C:
|
||||||
|
<programlisting>
|
||||||
|
#include "postgres.h"
|
||||||
|
#include "executor/spi.h"
|
||||||
|
#include "commands/trigger.h"
|
||||||
|
#include "utils/elog.h"
|
||||||
|
#include "fmgr.h"
|
||||||
|
#include "access/heapam.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
|
#include "catalog/pg_proc.h"
|
||||||
|
#include "catalog/pg_type.h"
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(plsample_call_handler);
|
||||||
|
|
||||||
|
Datum
|
||||||
|
plsample_call_handler(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
Datum retval;
|
||||||
|
|
||||||
|
if (CALLED_AS_TRIGGER(fcinfo))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Called as a trigger procedure
|
||||||
|
*/
|
||||||
|
TriggerData *trigdata = (TriggerData *) fcinfo->context;
|
||||||
|
|
||||||
|
retval = ...
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Called as a function
|
||||||
|
*/
|
||||||
|
|
||||||
|
retval = ...
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Only a few thousand lines of code have to be added instead of the
|
||||||
|
dots to complete the call handler. See <xref linkend="xfunc-c">
|
||||||
|
for information on how to compile it into a loadable module.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following commands then register the sample procedural
|
||||||
|
language:
|
||||||
|
<programlisting>
|
||||||
|
CREATE FUNCTION plsample_call_handler () RETURNS opaque
|
||||||
|
AS '/usr/local/pgsql/lib/plsample.so'
|
||||||
|
LANGUAGE C;
|
||||||
|
CREATE LANGUAGE plsample
|
||||||
|
HANDLER plsample_call_handler;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<!-- Keep this comment at the end of the file
|
<!-- Keep this comment at the end of the file
|
||||||
|
Loading…
x
Reference in New Issue
Block a user