Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit26abb50

Browse files
committed
Support PL/Tcl functions that return composite types and/or sets.
Jim Nasby, rather heavily editorialized by mePatch: <f2134651-14b3-efeb-f274-c69f3c084031@BlueTreble.com>
1 parent2178cbf commit26abb50

File tree

6 files changed

+545
-81
lines changed

6 files changed

+545
-81
lines changed

‎doc/src/sgml/pltcl.sgml

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ $$ LANGUAGE pltcl;
9494

9595
<para>
9696
The body of the function is simply a piece of Tcl script.
97-
When the function is called, the argument values are passedas
98-
variables <literal>$1</literal> ... <literal>$<replaceable>n</replaceable></literal> to the
99-
Tcl script. The result is returned
100-
from the Tcl code in the usual way, with a <literal>return</literal>
101-
statement.
97+
When the function is called, the argument values are passedto the
98+
Tcl script asvariablesnamed<literal>1</literal>
99+
... <literal><replaceable>n</replaceable></literal>. The result is
100+
returnedfrom the Tcl code in the usual way, with
101+
a <literal>return</literal>statement.
102102
</para>
103103

104104
<para>
@@ -173,17 +173,57 @@ $$ LANGUAGE pltcl;
173173
</para>
174174

175175
<para>
176-
There is currently no support for returning a composite-type
177-
result value, nor for returning sets.
176+
PL/Tcl functions can return composite-type results, too. To do this,
177+
the Tcl code must return a list of column name/value pairs matching
178+
the expected result type. Any column names omitted from the list
179+
are returned as nulls, and an error is raised if there are unexpected
180+
column names. Here is an example:
181+
182+
<programlisting>
183+
CREATE FUNCTION square_cube(in int, out squared int, out cubed int) AS $$
184+
return [list squared [expr {$1 * $1}] cubed [expr {$1 * $1 * $1}]]
185+
$$ LANGUAGE pltcl;
186+
</programlisting>
178187
</para>
179188

189+
<tip>
190+
<para>
191+
The result list can be made from an array representation of the
192+
desired tuple with the <literal>array get</> Tcl command. For example:
193+
194+
<programlisting>
195+
CREATE FUNCTION raise_pay(employee, delta int) RETURNS employee AS $$
196+
set 1(salary) [expr {$1(salary) + $2}]
197+
return [array get 1]
198+
$$ LANGUAGE pltcl;
199+
</programlisting>
200+
</para>
201+
</tip>
202+
180203
<para>
181-
<application>PL/Tcl</> does not currently have full support for
182-
domain types: it treats a domain the same as the underlying scalar
183-
type. This means that constraints associated with the domain will
184-
not be enforced. This is not an issue for function arguments, but
185-
it is a hazard if you declare a <application>PL/Tcl</> function
186-
as returning a domain type.
204+
PL/Tcl functions can return sets. To do this, the Tcl code should
205+
call <function>return_next</function> once per row to be returned,
206+
passing either the appropriate value when returning a scalar type,
207+
or a list of column name/value pairs when returning a composite type.
208+
Here is an example returning a scalar type:
209+
210+
<programlisting>
211+
CREATE FUNCTION sequence(int, int) RETURNS SETOF int AS $$
212+
for {set i $1} {$i &lt; $2} {incr i} {
213+
return_next $i
214+
}
215+
$$ LANGUAGE pltcl;
216+
</programlisting>
217+
218+
and here is one returning a composite type:
219+
220+
<programlisting>
221+
CREATE FUNCTION table_of_squares(int, int) RETURNS TABLE (x int, x2 int) AS $$
222+
for {set i $1} {$i &lt; $2} {incr i} {
223+
return_next [list x $i x2 [expr {$i * $i}]]
224+
}
225+
$$ LANGUAGE pltcl;
226+
</programlisting>
187227
</para>
188228

189229
</sect1>
@@ -195,10 +235,9 @@ $$ LANGUAGE pltcl;
195235
The argument values supplied to a PL/Tcl function's code are simply
196236
the input arguments converted to text form (just as if they had been
197237
displayed by a <command>SELECT</> statement). Conversely, the
198-
<literal>return</>
199-
command will accept any string that is acceptable input format for
200-
the function's declared return type. So, within the PL/Tcl function,
201-
all values are just text strings.
238+
<literal>return</> and <literal>return_next</> commands will accept
239+
any string that is acceptable input format for the function's declared
240+
result type, or for the specified column of a composite result type.
202241
</para>
203242

204243
</sect1>

‎src/pl/tcl/expected/pltcl_queries.out

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,64 @@ select tcl_lastoid('t2') > 0;
303303
t
304304
(1 row)
305305

306+
-- test some error cases
307+
CREATE FUNCTION tcl_error(OUT a int, OUT b int) AS $$return {$$ LANGUAGE pltcl;
308+
SELECT tcl_error();
309+
ERROR: missing close-brace
310+
CREATE FUNCTION bad_record(OUT a text, OUT b text) AS $$return [list a]$$ LANGUAGE pltcl;
311+
SELECT bad_record();
312+
ERROR: column name/value list must have even number of elements
313+
CREATE FUNCTION bad_field(OUT a text, OUT b text) AS $$return [list a 1 b 2 cow 3]$$ LANGUAGE pltcl;
314+
SELECT bad_field();
315+
ERROR: column name/value list contains nonexistent column name "cow"
316+
-- test compound return
317+
select * from tcl_test_cube_squared(5);
318+
squared | cubed
319+
---------+-------
320+
25 | 125
321+
(1 row)
322+
323+
-- test SRF
324+
select * from tcl_test_squared_rows(0,5);
325+
x | y
326+
---+----
327+
0 | 0
328+
1 | 1
329+
2 | 4
330+
3 | 9
331+
4 | 16
332+
(5 rows)
333+
334+
select * from tcl_test_sequence(0,5) as a;
335+
a
336+
---
337+
0
338+
1
339+
2
340+
3
341+
4
342+
(5 rows)
343+
344+
select 1, tcl_test_sequence(0,5);
345+
?column? | tcl_test_sequence
346+
----------+-------------------
347+
1 | 0
348+
1 | 1
349+
1 | 2
350+
1 | 3
351+
1 | 4
352+
(5 rows)
353+
354+
CREATE FUNCTION non_srf() RETURNS int AS $$return_next 1$$ LANGUAGE pltcl;
355+
select non_srf();
356+
ERROR: return_next cannot be used in non-set-returning functions
357+
CREATE FUNCTION bad_record_srf(OUT a text, OUT b text) RETURNS SETOF record AS $$
358+
return_next [list a]
359+
$$ LANGUAGE pltcl;
360+
SELECT bad_record_srf();
361+
ERROR: column name/value list must have even number of elements
362+
CREATE FUNCTION bad_field_srf(OUT a text, OUT b text) RETURNS SETOF record AS $$
363+
return_next [list a 1 b 2 cow 3]
364+
$$ LANGUAGE pltcl;
365+
SELECT bad_field_srf();
366+
ERROR: column name/value list contains nonexistent column name "cow"

‎src/pl/tcl/expected/pltcl_setup.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,19 @@ NOTICE: tclsnitch: ddl_command_start DROP TABLE
555555
NOTICE: tclsnitch: ddl_command_end DROP TABLE
556556
drop event trigger tcl_a_snitch;
557557
drop event trigger tcl_b_snitch;
558+
CREATE FUNCTION tcl_test_cube_squared(in int, out squared int, out cubed int) AS $$
559+
return [list squared [expr {$1 * $1}] cubed [expr {$1 * $1 * $1}]]
560+
$$ language pltcl;
561+
CREATE FUNCTION tcl_test_squared_rows(int,int) RETURNS TABLE (x int, y int) AS $$
562+
for {set i $1} {$i < $2} {incr i} {
563+
return_next [list y [expr {$i * $i}] x $i]
564+
}
565+
$$ language pltcl;
566+
CREATE FUNCTION tcl_test_sequence(int,int) RETURNS SETOF int AS $$
567+
for {set i $1} {$i < $2} {incr i} {
568+
return_next $i
569+
}
570+
$$ language pltcl;
558571
-- test use of errorCode in error handling
559572
create function tcl_error_handling_test() returns text as $$
560573
global errorCode

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp