2 -- Test result value processing
5 CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
10 SELECT * FROM perl_int(42);
12 CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
17 SELECT * FROM perl_int(42);
20 CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
24 SELECT perl_set_int(5);
25 SELECT * FROM perl_set_int(5);
27 CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
31 SELECT perl_set_int(5);
32 SELECT * FROM perl_set_int(5);
35 CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
37 CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
42 SELECT * FROM perl_row();
44 CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
45 return {f2 => 'hello', f1 => 1, f3 => 'world'};
49 SELECT * FROM perl_row();
52 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
57 SELECT * FROM perl_set();
59 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
61 { f1 => 1, f2 => 'Hello', f3 => 'World' },
63 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
68 SELECT * FROM perl_set();
70 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
72 { f1 => 1, f2 => 'Hello', f3 => 'World' },
73 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
74 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
79 SELECT * FROM perl_set();
83 CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
88 SELECT * FROM perl_record();
89 SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text);
91 CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
92 return {f2 => 'hello', f1 => 1, f3 => 'world'};
96 SELECT * FROM perl_record();
97 SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text);
100 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
104 SELECT perl_record_set();
105 SELECT * FROM perl_record_set();
106 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
108 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
110 { f1 => 1, f2 => 'Hello', f3 => 'World' },
112 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
116 SELECT perl_record_set();
117 SELECT * FROM perl_record_set();
118 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
120 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
122 { f1 => 1, f2 => 'Hello', f3 => 'World' },
123 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
124 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
128 SELECT perl_record_set();
129 SELECT * FROM perl_record_set();
130 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
132 CREATE OR REPLACE FUNCTION
133 perl_out_params(f1 out integer, f2 out text, f3 out text) AS $$
134 return {f2 => 'hello', f1 => 1, f3 => 'world'};
137 SELECT perl_out_params();
138 SELECT * FROM perl_out_params();
139 SELECT (perl_out_params()).f2;
141 CREATE OR REPLACE FUNCTION
142 perl_out_params_set(out f1 integer, out f2 text, out f3 text)
143 RETURNS SETOF record AS $$
145 { f1 => 1, f2 => 'Hello', f3 => 'World' },
146 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
147 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
151 SELECT perl_out_params_set();
152 SELECT * FROM perl_out_params_set();
153 SELECT (perl_out_params_set()).f3;
156 -- Check behavior with erroneous return values
159 CREATE TYPE footype AS (x INTEGER, y INTEGER);
161 CREATE OR REPLACE FUNCTION foo_good() RETURNS SETOF footype AS $$
168 SELECT * FROM foo_good();
170 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
171 return {y => 3, z => 4};
174 SELECT * FROM foo_bad();
176 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
180 SELECT * FROM foo_bad();
182 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
189 SELECT * FROM foo_bad();
191 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
195 SELECT * FROM foo_set_bad();
197 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
198 return {y => 3, z => 4};
201 SELECT * FROM foo_set_bad();
203 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
210 SELECT * FROM foo_set_bad();
212 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
218 SELECT * FROM foo_set_bad();
221 -- Check passing a tuple argument
224 CREATE OR REPLACE FUNCTION perl_get_field(footype, text) RETURNS integer AS $$
225 return $_[0]->{$_[1]};
228 SELECT perl_get_field((11,12), 'x');
229 SELECT perl_get_field((11,12), 'y');
230 SELECT perl_get_field((11,12), 'z');
236 CREATE OR REPLACE FUNCTION perl_srf_rn() RETURNS SETOF RECORD AS $$
238 for ("World", "PostgreSQL", "PL/Perl") {
239 return_next({f1=>++$i, f2=>'Hello', f3=>$_});
243 SELECT * from perl_srf_rn() AS (f1 INTEGER, f2 TEXT, f3 TEXT);
246 -- Test spi_query/spi_fetchrow
249 CREATE OR REPLACE FUNCTION perl_spi_func() RETURNS SETOF INTEGER AS $$
250 my $x = spi_query("select 1 as a union select 2 as a");
251 while (defined (my $y = spi_fetchrow($x))) {
252 return_next($y->{a});
256 SELECT * from perl_spi_func();
259 -- Test spi_fetchrow abort
261 CREATE OR REPLACE FUNCTION perl_spi_func2() RETURNS INTEGER AS $$
262 my $x = spi_query("select 1 as a union select 2 as a");
263 spi_cursor_close( $x);
266 SELECT * from perl_spi_func2();
270 --- Test recursion via SPI
274 CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
278 foreach my $x (1..$i)
280 return_next "hello $x";
285 my $cursor = spi_query("select * from recurse($z)");
286 while (defined(my $row = spi_fetchrow($cursor)))
288 return_next "recurse $i: $row->{recurse}";
295 SELECT * FROM recurse(2);
296 SELECT * FROM recurse(3);
300 --- Test arrary return
302 CREATE OR REPLACE FUNCTION array_of_text() RETURNS TEXT[][]
303 LANGUAGE plperl as $$
304 return [['a"b',undef,'c,d'],['e\\f',undef,'g']];
307 SELECT array_of_text();
310 -- Test spi_prepare/spi_exec_prepared/spi_freeplan
312 CREATE OR REPLACE FUNCTION perl_spi_prepared(INTEGER) RETURNS INTEGER AS $$
313 my $x = spi_prepare('select $1 AS a', 'INTEGER');
314 my $q = spi_exec_prepared( $x, $_[0] + 1);
316 return $q->{rows}->[0]->{a};
318 SELECT * from perl_spi_prepared(42);
321 -- Test spi_prepare/spi_query_prepared/spi_freeplan
323 CREATE OR REPLACE FUNCTION perl_spi_prepared_set(INTEGER, INTEGER) RETURNS SETOF INTEGER AS $$
324 my $x = spi_prepare('SELECT $1 AS a union select $2 as a', 'INT4', 'INT4');
325 my $q = spi_query_prepared( $x, 1+$_[0], 2+$_[1]);
326 while (defined (my $y = spi_fetchrow($q))) {
332 SELECT * from perl_spi_prepared_set(1,2);
335 -- Test prepare with a type with spaces
337 CREATE OR REPLACE FUNCTION perl_spi_prepared_double(double precision) RETURNS double precision AS $$
338 my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'DOUBLE PRECISION');
339 my $q = spi_query_prepared($x,$_[0]);
341 while (defined (my $y = spi_fetchrow($q))) {
347 SELECT perl_spi_prepared_double(4.35) as "double precision";
350 -- Test with a bad type
352 CREATE OR REPLACE FUNCTION perl_spi_prepared_bad(double precision) RETURNS double precision AS $$
353 my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'does_not_exist');
354 my $q = spi_query_prepared($x,$_[0]);
356 while (defined (my $y = spi_fetchrow($q))) {
362 SELECT perl_spi_prepared_bad(4.35) as "double precision";