|
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Chapter 55. Writing a Procedural Language Handler</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="nls-programmer.html" title="54.2. For the Programmer" /><link rel="next" href="fdwhandler.html" title="Chapter 56. Writing a Foreign Data Wrapper" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">Chapter 55. Writing a Procedural Language Handler</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="nls-programmer.html" title="54.2. For the Programmer">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="internals.html" title="Part VII. Internals">Up</a></td><th width="60%" align="center">Part VII. Internals</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="fdwhandler.html" title="Chapter 56. Writing a Foreign Data Wrapper">Next</a></td></tr></table><hr></hr></div><div class="chapter" id="PLHANDLER"><div class="titlepage"><div><div><h2 class="title">Chapter 55. Writing a Procedural Language Handler</h2></div></div></div><a id="id-1.10.8.2" class="indexterm"></a><p>
- All calls to functions that are written in a language other than
- the current <span class="quote">“<span class="quote">version 1</span>”</span> interface for compiled
- languages (this includes functions in user-defined procedural languages
- and functions written in SQL) go through a <em class="firstterm">call handler</em>
- 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 chapter outlines
- how a new procedural language's call handler can be written.
- </p><p>
- The call handler for a procedural language is a
- <span class="quote">“<span class="quote">normal</span>”</span> function that must be written in a compiled
- language such as C, using the version-1 interface, and registered
- with <span class="productname">PostgreSQL</span> as taking no arguments
- and returning the type <code class="type">language_handler</code>. This
- special pseudo-type identifies the function as a call handler and
- prevents it from being called directly in SQL commands.
- For more details on C language calling conventions and dynamic loading,
- see <a class="xref" href="xfunc-c.html" title="37.10. C-Language Functions">Section 37.10</a>.
- </p><p>
- The call handler is called in the same way as any other function:
- It receives a pointer to a
- <code class="structname">FunctionCallInfoBaseData</code> <code class="type">struct</code> containing
- argument values and information about the called function, and it
- is expected to return a <code class="type">Datum</code> result (and possibly
- set the <code class="structfield">isnull</code> field of the
- <code class="structname">FunctionCallInfoBaseData</code> structure, if it wishes
- to return an SQL null result). The difference between a call
- handler and an ordinary callee function is that the
- <code class="structfield">flinfo->fn_oid</code> field of the
- <code class="structname">FunctionCallInfoBaseData</code> structure 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.
- </p><p>
- It's up to the call handler to fetch the entry of the function from the
- <code class="classname">pg_proc</code> system catalog and to analyze the argument
- and return types of the called function. The <code class="literal">AS</code> clause from the
- <code class="command">CREATE FUNCTION</code> command for the function will be found
- in the <code class="literal">prosrc</code> column of the
- <code class="classname">pg_proc</code> row. This is commonly source
- text in the procedural language, but in theory it could be something else,
- such as a path name to a file, or anything else that tells the call handler
- what to do in detail.
- </p><p>
- 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
- <code class="structfield">flinfo->fn_extra</code> field. This will
- initially be <code class="symbol">NULL</code>, but can be set by the call handler to point at
- information about the called function. On subsequent calls, if
- <code class="structfield">flinfo->fn_extra</code> is already non-<code class="symbol">NULL</code>
- then it can be used and the information lookup step skipped. The
- call handler must make sure that
- <code class="structfield">flinfo->fn_extra</code> is made to point at
- memory that will live at least until the end of the current query,
- since an <code class="structname">FmgrInfo</code> data structure could be
- kept that long. One way to do this is to allocate the extra data
- in the memory context specified by
- <code class="structfield">flinfo->fn_mcxt</code>; such data will
- normally have the same lifespan as the
- <code class="structname">FmgrInfo</code> itself. But the handler could
- also choose to use a longer-lived memory context so that it can cache
- function definition information across queries.
- </p><p>
- When a procedural-language function is invoked as a trigger, no arguments
- are passed in the usual way, but the
- <code class="structname">FunctionCallInfoBaseData</code>'s
- <code class="structfield">context</code> field points at a
- <code class="structname">TriggerData</code> structure, rather than being <code class="symbol">NULL</code>
- as it is in a plain function call. A language handler should
- provide mechanisms for procedural-language functions to get at the trigger
- information.
- </p><p>
- This is a template for a procedural-language handler written in C:
- </p><pre class="programlisting">
- #include "postgres.h"
- #include "executor/spi.h"
- #include "commands/trigger.h"
- #include "fmgr.h"
- #include "access/heapam.h"
- #include "utils/syscache.h"
- #include "catalog/pg_proc.h"
- #include "catalog/pg_type.h"
-
- PG_MODULE_MAGIC;
-
- 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 function
- */
- TriggerData *trigdata = (TriggerData *) fcinfo->context;
-
- retval = ...
- }
- else
- {
- /*
- * Called as a function
- */
-
- retval = ...
- }
-
- return retval;
- }
- </pre><p>
- Only a few thousand lines of code have to be added instead of the
- dots to complete the call handler.
- </p><p>
- After having compiled the handler function into a loadable module
- (see <a class="xref" href="xfunc-c.html#DFUNC" title="37.10.5. Compiling and Linking Dynamically-Loaded Functions">Section 37.10.5</a>), the following commands then
- register the sample procedural language:
- </p><pre class="programlisting">
- CREATE FUNCTION plsample_call_handler() RETURNS language_handler
- AS '<em class="replaceable"><code>filename</code></em>'
- LANGUAGE C;
- CREATE LANGUAGE plsample
- HANDLER plsample_call_handler;
- </pre><p>
- </p><p>
- Although providing a call handler is sufficient to create a minimal
- procedural language, there are two other functions that can optionally
- be provided to make the language more convenient to use. These
- are a <em class="firstterm">validator</em> and an
- <em class="firstterm">inline handler</em>. A validator can be provided
- to allow language-specific checking to be done during
- <a class="xref" href="sql-createfunction.html" title="CREATE FUNCTION"><span class="refentrytitle">CREATE FUNCTION</span></a>.
- An inline handler can be provided to allow the language to support
- anonymous code blocks executed via the <a class="xref" href="sql-do.html" title="DO"><span class="refentrytitle">DO</span></a> command.
- </p><p>
- If a validator is provided by a procedural language, it
- must be declared as a function taking a single parameter of type
- <code class="type">oid</code>. The validator's result is ignored, so it is customarily
- declared to return <code class="type">void</code>. The validator will be called at
- the end of a <code class="command">CREATE FUNCTION</code> command that has created
- or updated a function written in the procedural language.
- The passed-in OID is the OID of the function's <code class="classname">pg_proc</code>
- row. The validator must fetch this row in the usual way, and do
- whatever checking is appropriate.
- First, call <code class="function">CheckFunctionValidatorAccess()</code> to diagnose
- explicit calls to the validator that the user could not achieve through
- <code class="command">CREATE FUNCTION</code>. Typical checks then include verifying
- that the function's argument and result types are supported by the
- language, and that the function's body is syntactically correct
- in the language. If the validator finds the function to be okay,
- it should just return. If it finds an error, it should report that
- via the normal <code class="function">ereport()</code> error reporting mechanism.
- Throwing an error will force a transaction rollback and thus prevent
- the incorrect function definition from being committed.
- </p><p>
- Validator functions should typically honor the <a class="xref" href="runtime-config-client.html#GUC-CHECK-FUNCTION-BODIES">check_function_bodies</a> parameter: if it is turned off then
- any expensive or context-sensitive checking should be skipped. If the
- language provides for code execution at compilation time, the validator
- must suppress checks that would induce such execution. In particular,
- this parameter is turned off by <span class="application">pg_dump</span> so that it can
- load procedural language functions without worrying about side effects or
- dependencies of the function bodies on other database objects.
- (Because of this requirement, the call handler should avoid
- assuming that the validator has fully checked the function. The point
- of having a validator is not to let the call handler omit checks, but
- to notify the user immediately if there are obvious errors in a
- <code class="command">CREATE FUNCTION</code> command.)
- While the choice of exactly what to check is mostly left to the
- discretion of the validator function, note that the core
- <code class="command">CREATE FUNCTION</code> code only executes <code class="literal">SET</code> clauses
- attached to a function when <code class="varname">check_function_bodies</code> is on.
- Therefore, checks whose results might be affected by GUC parameters
- definitely should be skipped when <code class="varname">check_function_bodies</code> is
- off, to avoid false failures when reloading a dump.
- </p><p>
- If an inline handler is provided by a procedural language, it
- must be declared as a function taking a single parameter of type
- <code class="type">internal</code>. The inline handler's result is ignored, so it is
- customarily declared to return <code class="type">void</code>. The inline handler
- will be called when a <code class="command">DO</code> statement is executed specifying
- the procedural language. The parameter actually passed is a pointer
- to an <code class="structname">InlineCodeBlock</code> struct, which contains information
- about the <code class="command">DO</code> statement's parameters, in particular the
- text of the anonymous code block to be executed. The inline handler
- should execute this code and return.
- </p><p>
- It's recommended that you wrap all these function declarations,
- as well as the <code class="command">CREATE LANGUAGE</code> command itself, into
- an <em class="firstterm">extension</em> so that a simple <code class="command">CREATE EXTENSION</code>
- command is sufficient to install the language. See
- <a class="xref" href="extend-extensions.html" title="37.17. Packaging Related Objects into an Extension">Section 37.17</a> for information about writing
- extensions.
- </p><p>
- The procedural languages included in the standard distribution
- are good references when trying to write your own language handler.
- Look into the <code class="filename">src/pl</code> subdirectory of the source tree.
- The <a class="xref" href="sql-createlanguage.html" title="CREATE LANGUAGE"><span class="refentrytitle">CREATE LANGUAGE</span></a>
- reference page also has some useful details.
- </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="nls-programmer.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="internals.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="fdwhandler.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">54.2. For the Programmer </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 56. Writing a Foreign Data Wrapper</td></tr></table></div></body></html>
|