2 -- Test result value processing
4 CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
13 SELECT * FROM perl_int(42);
19 CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
28 SELECT * FROM perl_int(42);
34 CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
37 SELECT perl_set_int(5);
42 SELECT * FROM perl_set_int(5);
47 CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
50 SELECT perl_set_int(5);
61 SELECT * FROM perl_set_int(5);
72 CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
73 CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
82 SELECT * FROM perl_row();
88 CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
89 return {f2 => 'hello', f1 => 1, f3 => 'world'};
97 SELECT * FROM perl_row();
103 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
111 SELECT * FROM perl_set();
116 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
118 { f1 => 1, f2 => 'Hello', f3 => 'World' },
120 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
124 ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash
125 SELECT * FROM perl_set();
126 ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash
127 CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
129 { f1 => 1, f2 => 'Hello', f3 => 'World' },
130 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
131 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
136 ----------------------
142 SELECT * FROM perl_set();
144 ----+-------+------------
146 2 | Hello | PostgreSQL
150 CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
153 SELECT perl_record();
159 SELECT * FROM perl_record();
160 ERROR: a column definition list is required for functions returning "record"
161 LINE 1: SELECT * FROM perl_record();
163 SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text);
169 CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
170 return {f2 => 'hello', f1 => 1, f3 => 'world'};
172 SELECT perl_record();
173 ERROR: function returning record called in context that cannot accept type record
174 SELECT * FROM perl_record();
175 ERROR: a column definition list is required for functions returning "record"
176 LINE 1: SELECT * FROM perl_record();
178 SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text);
184 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
187 SELECT perl_record_set();
188 ERROR: set-valued function called in context that cannot accept a set
189 SELECT * FROM perl_record_set();
190 ERROR: a column definition list is required for functions returning "record"
191 LINE 1: SELECT * FROM perl_record_set();
193 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
198 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
200 { f1 => 1, f2 => 'Hello', f3 => 'World' },
202 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
205 SELECT perl_record_set();
206 ERROR: set-valued function called in context that cannot accept a set
207 SELECT * FROM perl_record_set();
208 ERROR: a column definition list is required for functions returning "record"
209 LINE 1: SELECT * FROM perl_record_set();
211 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
212 ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash
213 CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
215 { f1 => 1, f2 => 'Hello', f3 => 'World' },
216 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
217 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
220 SELECT perl_record_set();
221 ERROR: set-valued function called in context that cannot accept a set
222 SELECT * FROM perl_record_set();
223 ERROR: a column definition list is required for functions returning "record"
224 LINE 1: SELECT * FROM perl_record_set();
226 SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
228 ----+-------+------------
230 2 | Hello | PostgreSQL
234 CREATE OR REPLACE FUNCTION
235 perl_out_params(f1 out integer, f2 out text, f3 out text) AS $$
236 return {f2 => 'hello', f1 => 1, f3 => 'world'};
238 SELECT perl_out_params();
244 SELECT * FROM perl_out_params();
250 SELECT (perl_out_params()).f2;
256 CREATE OR REPLACE FUNCTION
257 perl_out_params_set(out f1 integer, out f2 text, out f3 text)
258 RETURNS SETOF record AS $$
260 { f1 => 1, f2 => 'Hello', f3 => 'World' },
261 { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
262 { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
265 SELECT perl_out_params_set();
267 ----------------------
273 SELECT * FROM perl_out_params_set();
275 ----+-------+------------
277 2 | Hello | PostgreSQL
281 SELECT (perl_out_params_set()).f3;
290 -- Check behavior with erroneous return values
292 CREATE TYPE footype AS (x INTEGER, y INTEGER);
293 CREATE OR REPLACE FUNCTION foo_good() RETURNS SETOF footype AS $$
299 SELECT * FROM foo_good();
306 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
307 return {y => 3, z => 4};
309 SELECT * FROM foo_bad();
310 ERROR: Perl hash contains nonexistent column "z"
311 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
314 SELECT * FROM foo_bad();
315 ERROR: composite-returning PL/Perl function must return reference to hash
316 CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
322 SELECT * FROM foo_bad();
323 ERROR: composite-returning PL/Perl function must return reference to hash
324 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
327 SELECT * FROM foo_set_bad();
328 ERROR: set-returning PL/Perl function must return reference to array or use return_next
329 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
330 return {y => 3, z => 4};
332 SELECT * FROM foo_set_bad();
333 ERROR: set-returning PL/Perl function must return reference to array or use return_next
334 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
340 SELECT * FROM foo_set_bad();
341 ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash
342 CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
347 SELECT * FROM foo_set_bad();
348 ERROR: Perl hash contains nonexistent column "z"
350 -- Check passing a tuple argument
352 CREATE OR REPLACE FUNCTION perl_get_field(footype, text) RETURNS integer AS $$
353 return $_[0]->{$_[1]};
355 SELECT perl_get_field((11,12), 'x');
361 SELECT perl_get_field((11,12), 'y');
367 SELECT perl_get_field((11,12), 'z');
376 CREATE OR REPLACE FUNCTION perl_srf_rn() RETURNS SETOF RECORD AS $$
378 for ("World", "PostgreSQL", "PL/Perl") {
379 return_next({f1=>++$i, f2=>'Hello', f3=>$_});
383 SELECT * from perl_srf_rn() AS (f1 INTEGER, f2 TEXT, f3 TEXT);
385 ----+-------+------------
387 2 | Hello | PostgreSQL
392 -- Test spi_query/spi_fetchrow
394 CREATE OR REPLACE FUNCTION perl_spi_func() RETURNS SETOF INTEGER AS $$
395 my $x = spi_query("select 1 as a union select 2 as a");
396 while (defined (my $y = spi_fetchrow($x))) {
397 return_next($y->{a});
401 SELECT * from perl_spi_func();
409 -- Test spi_fetchrow abort
411 CREATE OR REPLACE FUNCTION perl_spi_func2() RETURNS INTEGER AS $$
412 my $x = spi_query("select 1 as a union select 2 as a");
413 spi_cursor_close( $x);
416 SELECT * from perl_spi_func2();
423 --- Test recursion via SPI
425 CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
429 foreach my $x (1..$i)
431 return_next "hello $x";
436 my $cursor = spi_query("select * from recurse($z)");
437 while (defined(my $row = spi_fetchrow($cursor)))
439 return_next "recurse $i: $row->{recurse}";
445 SELECT * FROM recurse(2);
452 SELECT * FROM recurse(3);
463 --- Test arrary return
465 CREATE OR REPLACE FUNCTION array_of_text() RETURNS TEXT[][]
466 LANGUAGE plperl as $$
467 return [['a"b',undef,'c,d'],['e\\f',undef,'g']];
469 SELECT array_of_text();
471 ---------------------------------------
472 {{"a\"b",NULL,"c,d"},{"e\\f",NULL,g}}
476 -- Test spi_prepare/spi_exec_prepared/spi_freeplan
478 CREATE OR REPLACE FUNCTION perl_spi_prepared(INTEGER) RETURNS INTEGER AS $$
479 my $x = spi_prepare('select $1 AS a', 'INTEGER');
480 my $q = spi_exec_prepared( $x, $_[0] + 1);
482 return $q->{rows}->[0]->{a};
484 SELECT * from perl_spi_prepared(42);
491 -- Test spi_prepare/spi_query_prepared/spi_freeplan
493 CREATE OR REPLACE FUNCTION perl_spi_prepared_set(INTEGER, INTEGER) RETURNS SETOF INTEGER AS $$
494 my $x = spi_prepare('SELECT $1 AS a union select $2 as a', 'INT4', 'INT4');
495 my $q = spi_query_prepared( $x, 1+$_[0], 2+$_[1]);
496 while (defined (my $y = spi_fetchrow($q))) {
502 SELECT * from perl_spi_prepared_set(1,2);
503 perl_spi_prepared_set
504 -----------------------
510 -- Test prepare with a type with spaces
512 CREATE OR REPLACE FUNCTION perl_spi_prepared_double(double precision) RETURNS double precision AS $$
513 my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'DOUBLE PRECISION');
514 my $q = spi_query_prepared($x,$_[0]);
516 while (defined (my $y = spi_fetchrow($q))) {
522 SELECT perl_spi_prepared_double(4.35) as "double precision";
529 -- Test with a bad type
531 CREATE OR REPLACE FUNCTION perl_spi_prepared_bad(double precision) RETURNS double precision AS $$
532 my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'does_not_exist');
533 my $q = spi_query_prepared($x,$_[0]);
535 while (defined (my $y = spi_fetchrow($q))) {
541 SELECT perl_spi_prepared_bad(4.35) as "double precision";
542 ERROR: error from Perl function "perl_spi_prepared_bad": type "does_not_exist" does not exist at line 2.