mirror of
https://git.postgresql.org/git/postgresql.git
synced 2026-02-15 10:57:02 +08:00
We must stay in the function's SPI context until done calling the iterator that returns the set result. Otherwise, any attempt to invoke SPI features in the python code called by the iterator will malfunction. Diagnosis and patch by Jan Urbanski, per bug report from Jean-Baptiste Quenot. Back-patch to 8.2; there was no support for SRFs in previous versions of plpython.
127 lines
2.5 KiB
Plaintext
127 lines
2.5 KiB
Plaintext
--
|
|
-- Test returning SETOF
|
|
--
|
|
CREATE FUNCTION test_setof_error() RETURNS SETOF text AS $$
|
|
return 37
|
|
$$ LANGUAGE plpythonu;
|
|
SELECT test_setof_error();
|
|
ERROR: returned object cannot be iterated
|
|
DETAIL: PL/Python set-returning functions must return an iterable object.
|
|
CONTEXT: PL/Python function "test_setof_error"
|
|
CREATE FUNCTION test_setof_as_list(count integer, content text) RETURNS SETOF text AS $$
|
|
return [ content ]*count
|
|
$$ LANGUAGE plpythonu;
|
|
CREATE FUNCTION test_setof_as_tuple(count integer, content text) RETURNS SETOF text AS $$
|
|
t = ()
|
|
for i in range(count):
|
|
t += ( content, )
|
|
return t
|
|
$$ LANGUAGE plpythonu;
|
|
CREATE FUNCTION test_setof_as_iterator(count integer, content text) RETURNS SETOF text AS $$
|
|
class producer:
|
|
def __init__ (self, icount, icontent):
|
|
self.icontent = icontent
|
|
self.icount = icount
|
|
def __iter__ (self):
|
|
return self
|
|
def next (self):
|
|
if self.icount == 0:
|
|
raise StopIteration
|
|
self.icount -= 1
|
|
return self.icontent
|
|
return producer(count, content)
|
|
$$ LANGUAGE plpythonu;
|
|
CREATE FUNCTION test_setof_spi_in_iterator() RETURNS SETOF text AS
|
|
$$
|
|
for s in ('Hello', 'Brave', 'New', 'World'):
|
|
plpy.execute('select 1')
|
|
yield s
|
|
plpy.execute('select 2')
|
|
$$
|
|
LANGUAGE plpythonu;
|
|
-- Test set returning functions
|
|
SELECT test_setof_as_list(0, 'list');
|
|
test_setof_as_list
|
|
--------------------
|
|
(0 rows)
|
|
|
|
SELECT test_setof_as_list(1, 'list');
|
|
test_setof_as_list
|
|
--------------------
|
|
list
|
|
(1 row)
|
|
|
|
SELECT test_setof_as_list(2, 'list');
|
|
test_setof_as_list
|
|
--------------------
|
|
list
|
|
list
|
|
(2 rows)
|
|
|
|
SELECT test_setof_as_list(2, null);
|
|
test_setof_as_list
|
|
--------------------
|
|
|
|
|
|
(2 rows)
|
|
|
|
SELECT test_setof_as_tuple(0, 'tuple');
|
|
test_setof_as_tuple
|
|
---------------------
|
|
(0 rows)
|
|
|
|
SELECT test_setof_as_tuple(1, 'tuple');
|
|
test_setof_as_tuple
|
|
---------------------
|
|
tuple
|
|
(1 row)
|
|
|
|
SELECT test_setof_as_tuple(2, 'tuple');
|
|
test_setof_as_tuple
|
|
---------------------
|
|
tuple
|
|
tuple
|
|
(2 rows)
|
|
|
|
SELECT test_setof_as_tuple(2, null);
|
|
test_setof_as_tuple
|
|
---------------------
|
|
|
|
|
|
(2 rows)
|
|
|
|
SELECT test_setof_as_iterator(0, 'list');
|
|
test_setof_as_iterator
|
|
------------------------
|
|
(0 rows)
|
|
|
|
SELECT test_setof_as_iterator(1, 'list');
|
|
test_setof_as_iterator
|
|
------------------------
|
|
list
|
|
(1 row)
|
|
|
|
SELECT test_setof_as_iterator(2, 'list');
|
|
test_setof_as_iterator
|
|
------------------------
|
|
list
|
|
list
|
|
(2 rows)
|
|
|
|
SELECT test_setof_as_iterator(2, null);
|
|
test_setof_as_iterator
|
|
------------------------
|
|
|
|
|
|
(2 rows)
|
|
|
|
SELECT test_setof_spi_in_iterator();
|
|
test_setof_spi_in_iterator
|
|
----------------------------
|
|
Hello
|
|
Brave
|
|
New
|
|
World
|
|
(4 rows)
|
|
|