1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!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>42.2. PL/Tcl Functions and Arguments</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 Vsnapshot" /><link rel="prev" href="pltcl-overview.html" title="42.1. Overview" /><link rel="next" href="pltcl-data.html" title="42.3. Data Values in PL/Tcl" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">42.2. PL/Tcl Functions and Arguments</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="pltcl-overview.html" title="42.1. Overview">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="pltcl.html" title="Chapter 42. PL/Tcl — Tcl Procedural Language">Up</a></td><th width="60%" align="center">Chapter 42. PL/Tcl — Tcl Procedural Language</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="pltcl-data.html" title="42.3. Data Values in PL/Tcl">Next</a></td></tr></table><hr /></div><div class="sect1" id="PLTCL-FUNCTIONS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">42.2. PL/Tcl Functions and Arguments <a href="#PLTCL-FUNCTIONS" class="id_link">#</a></h2></div></div></div><p>
3 To create a function in the <span class="application">PL/Tcl</span> language, use
4 the standard <a class="xref" href="sql-createfunction.html" title="CREATE FUNCTION"><span class="refentrytitle">CREATE FUNCTION</span></a> syntax:
6 </p><pre class="programlisting">
7 CREATE FUNCTION <em class="replaceable"><code>funcname</code></em> (<em class="replaceable"><code>argument-types</code></em>) RETURNS <em class="replaceable"><code>return-type</code></em> AS $$
12 <span class="application">PL/TclU</span> is the same, except that the language has to be specified as
13 <code class="literal">pltclu</code>.
15 The body of the function is simply a piece of Tcl script.
16 When the function is called, the argument values are passed to the
17 Tcl script as variables named <code class="literal">1</code>
18 ... <code class="literal"><em class="replaceable"><code>n</code></em></code>. The result is
19 returned from the Tcl code in the usual way, with
20 a <code class="literal">return</code> statement. In a procedure, the return value
21 from the Tcl code is ignored.
23 For example, a function
24 returning the greater of two integer values could be defined as:
26 </p><pre class="programlisting">
27 CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
28 if {$1 > $2} {return $1}
30 $$ LANGUAGE pltcl STRICT;
33 Note the clause <code class="literal">STRICT</code>, which saves us from
34 having to think about null input values: if a null value is passed, the
35 function will not be called at all, but will just return a null
38 In a nonstrict function,
39 if the actual value of an argument is null, the corresponding
40 <code class="literal">$<em class="replaceable"><code>n</code></em></code> variable will be set to an empty string.
41 To detect whether a particular argument is null, use the function
42 <code class="literal">argisnull</code>. For example, suppose that we wanted <code class="function">tcl_max</code>
43 with one null and one nonnull argument to return the nonnull
44 argument, rather than null:
46 </p><pre class="programlisting">
47 CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
49 if {[argisnull 2]} { return_null }
52 if {[argisnull 2]} { return $1 }
53 if {$1 > $2} {return $1}
59 to return a null value from a PL/Tcl function, execute
60 <code class="literal">return_null</code>. This can be done whether the
61 function is strict or not.
63 Composite-type arguments are passed to the function as Tcl
64 arrays. The element names of the array are the attribute names
65 of the composite type. If an attribute in the passed row has the
66 null value, it will not appear in the array. Here is an example:
68 </p><pre class="programlisting">
69 CREATE TABLE employee (
75 CREATE FUNCTION overpaid(employee) RETURNS boolean AS $$
76 if {200000.0 < $1(salary)} {
79 if {$1(age) < 30 && 100000.0 < $1(salary)} {
86 PL/Tcl functions can return composite-type results, too. To do this,
87 the Tcl code must return a list of column name/value pairs matching
88 the expected result type. Any column names omitted from the list
89 are returned as nulls, and an error is raised if there are unexpected
90 column names. Here is an example:
92 </p><pre class="programlisting">
93 CREATE FUNCTION square_cube(in int, out squared int, out cubed int) AS $$
94 return [list squared [expr {$1 * $1}] cubed [expr {$1 * $1 * $1}]]
98 Output arguments of procedures are returned in the same way, for example:
100 </p><pre class="programlisting">
101 CREATE PROCEDURE tcl_triple(INOUT a integer, INOUT b integer) AS $$
102 return [list a [expr {$1 * 3}] b [expr {$2 * 3}]]
105 CALL tcl_triple(5, 10);
107 </p><div class="tip"><h3 class="title">Tip</h3><p>
108 The result list can be made from an array representation of the
109 desired tuple with the <code class="literal">array get</code> Tcl command. For example:
111 </p><pre class="programlisting">
112 CREATE FUNCTION raise_pay(employee, delta int) RETURNS employee AS $$
113 set 1(salary) [expr {$1(salary) + $2}]
118 PL/Tcl functions can return sets. To do this, the Tcl code should
119 call <code class="function">return_next</code> once per row to be returned,
120 passing either the appropriate value when returning a scalar type,
121 or a list of column name/value pairs when returning a composite type.
122 Here is an example returning a scalar type:
124 </p><pre class="programlisting">
125 CREATE FUNCTION sequence(int, int) RETURNS SETOF int AS $$
126 for {set i $1} {$i < $2} {incr i} {
132 and here is one returning a composite type:
134 </p><pre class="programlisting">
135 CREATE FUNCTION table_of_squares(int, int) RETURNS TABLE (x int, x2 int) AS $$
136 for {set i $1} {$i < $2} {incr i} {
137 return_next [list x $i x2 [expr {$i * $i}]]
141 </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="pltcl-overview.html" title="42.1. Overview">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="pltcl.html" title="Chapter 42. PL/Tcl — Tcl Procedural Language">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="pltcl-data.html" title="42.3. Data Values in PL/Tcl">Next</a></td></tr><tr><td width="40%" align="left" valign="top">42.1. Overview </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 42.3. Data Values in PL/Tcl</td></tr></table></div></body></html>