2 Chapter 57. Writing a Procedural Language Handler
4 All calls to functions that are written in a language other than the
5 current “version 1” interface for compiled languages (this includes
6 functions in user-defined procedural languages and functions written in
7 SQL) go through a call handler function for the specific language. It
8 is the responsibility of the call handler to execute the function in a
9 meaningful way, such as by interpreting the supplied source text. This
10 chapter outlines how a new procedural language's call handler can be
13 The call handler for a procedural language is a “normal” function that
14 must be written in a compiled language such as C, using the version-1
15 interface, and registered with PostgreSQL as taking no arguments and
16 returning the type language_handler. This special pseudo-type
17 identifies the function as a call handler and prevents it from being
18 called directly in SQL commands. For more details on C language calling
19 conventions and dynamic loading, see Section 36.10.
21 The call handler is called in the same way as any other function: It
22 receives a pointer to a FunctionCallInfoBaseData struct containing
23 argument values and information about the called function, and it is
24 expected to return a Datum result (and possibly set the isnull field of
25 the FunctionCallInfoBaseData structure, if it wishes to return an SQL
26 null result). The difference between a call handler and an ordinary
27 callee function is that the flinfo->fn_oid field of the
28 FunctionCallInfoBaseData structure will contain the OID of the actual
29 function to be called, not of the call handler itself. The call handler
30 must use this field to determine which function to execute. Also, the
31 passed argument list has been set up according to the declaration of
32 the target function, not of the call handler.
34 It's up to the call handler to fetch the entry of the function from the
35 pg_proc system catalog and to analyze the argument and return types of
36 the called function. The AS clause from the CREATE FUNCTION command for
37 the function will be found in the prosrc column of the pg_proc row.
38 This is commonly source text in the procedural language, but in theory
39 it could be something else, such as a path name to a file, or anything
40 else that tells the call handler what to do in detail.
42 Often, the same function is called many times per SQL statement. A call
43 handler can avoid repeated lookups of information about the called
44 function by using the flinfo->fn_extra field. This will initially be
45 NULL, but can be set by the call handler to point at information about
46 the called function. On subsequent calls, if flinfo->fn_extra is
47 already non-NULL then it can be used and the information lookup step
48 skipped. The call handler must make sure that flinfo->fn_extra is made
49 to point at memory that will live at least until the end of the current
50 query, since an FmgrInfo data structure could be kept that long. One
51 way to do this is to allocate the extra data in the memory context
52 specified by flinfo->fn_mcxt; such data will normally have the same
53 lifespan as the FmgrInfo itself. But the handler could also choose to
54 use a longer-lived memory context so that it can cache function
55 definition information across queries.
57 When a procedural-language function is invoked as a trigger, no
58 arguments are passed in the usual way, but the
59 FunctionCallInfoBaseData's context field points at a TriggerData
60 structure, rather than being NULL as it is in a plain function call. A
61 language handler should provide mechanisms for procedural-language
62 functions to get at the trigger information.
64 A template for a procedural-language handler written as a C extension
65 is provided in src/test/modules/plsample. This is a working sample
66 demonstrating one way to create a procedural-language handler, process
67 parameters, and return a value.
69 Although providing a call handler is sufficient to create a minimal
70 procedural language, there are two other functions that can optionally
71 be provided to make the language more convenient to use. These are a
72 validator and an inline handler. A validator can be provided to allow
73 language-specific checking to be done during CREATE FUNCTION. An inline
74 handler can be provided to allow the language to support anonymous code
75 blocks executed via the DO command.
77 If a validator is provided by a procedural language, it must be
78 declared as a function taking a single parameter of type oid. The
79 validator's result is ignored, so it is customarily declared to return
80 void. The validator will be called at the end of a CREATE FUNCTION
81 command that has created or updated a function written in the
82 procedural language. The passed-in OID is the OID of the function's
83 pg_proc row. The validator must fetch this row in the usual way, and do
84 whatever checking is appropriate. First, call
85 CheckFunctionValidatorAccess() to diagnose explicit calls to the
86 validator that the user could not achieve through CREATE FUNCTION.
87 Typical checks then include verifying that the function's argument and
88 result types are supported by the language, and that the function's
89 body is syntactically correct in the language. If the validator finds
90 the function to be okay, it should just return. If it finds an error,
91 it should report that via the normal ereport() error reporting
92 mechanism. Throwing an error will force a transaction rollback and thus
93 prevent the incorrect function definition from being committed.
95 Validator functions should typically honor the check_function_bodies
96 parameter: if it is turned off then any expensive or context-sensitive
97 checking should be skipped. If the language provides for code execution
98 at compilation time, the validator must suppress checks that would
99 induce such execution. In particular, this parameter is turned off by
100 pg_dump so that it can load procedural language functions without
101 worrying about side effects or dependencies of the function bodies on
102 other database objects. (Because of this requirement, the call handler
103 should avoid assuming that the validator has fully checked the
104 function. The point of having a validator is not to let the call
105 handler omit checks, but to notify the user immediately if there are
106 obvious errors in a CREATE FUNCTION command.) While the choice of
107 exactly what to check is mostly left to the discretion of the validator
108 function, note that the core CREATE FUNCTION code only executes SET
109 clauses attached to a function when check_function_bodies is on.
110 Therefore, checks whose results might be affected by GUC parameters
111 definitely should be skipped when check_function_bodies is off, to
112 avoid false failures when restoring a dump.
114 If an inline handler is provided by a procedural language, it must be
115 declared as a function taking a single parameter of type internal. The
116 inline handler's result is ignored, so it is customarily declared to
117 return void. The inline handler will be called when a DO statement is
118 executed specifying the procedural language. The parameter actually
119 passed is a pointer to an InlineCodeBlock struct, which contains
120 information about the DO statement's parameters, in particular the text
121 of the anonymous code block to be executed. The inline handler should
122 execute this code and return.
124 It's recommended that you wrap all these function declarations, as well
125 as the CREATE LANGUAGE command itself, into an extension so that a
126 simple CREATE EXTENSION command is sufficient to install the language.
127 See Section 36.17 for information about writing extensions.
129 The procedural languages included in the standard distribution are good
130 references when trying to write your own language handler. Look into
131 the src/pl subdirectory of the source tree. The CREATE LANGUAGE
132 reference page also has some useful details.