mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Allocate PLyResultObject.tupdesc in TopMemoryContext, because its lifetime is the lifetime of the Python object and it shouldn't be freed by some other memory context, such as one controlled by SPI. We trust that the Python object will clean up its own memory. Before, this would crash the included regression test case by trying to use memory that was already freed. reported by Asif Naeem, analysis by Tom Lane
77 lines
1.9 KiB
PL/PgSQL
77 lines
1.9 KiB
PL/PgSQL
--
|
|
-- Test returning SETOF
|
|
--
|
|
|
|
CREATE FUNCTION test_setof_error() RETURNS SETOF text AS $$
|
|
return 37
|
|
$$ LANGUAGE plpythonu;
|
|
|
|
SELECT 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');
|
|
SELECT test_setof_as_list(1, 'list');
|
|
SELECT test_setof_as_list(2, 'list');
|
|
SELECT test_setof_as_list(2, null);
|
|
|
|
SELECT test_setof_as_tuple(0, 'tuple');
|
|
SELECT test_setof_as_tuple(1, 'tuple');
|
|
SELECT test_setof_as_tuple(2, 'tuple');
|
|
SELECT test_setof_as_tuple(2, null);
|
|
|
|
SELECT test_setof_as_iterator(0, 'list');
|
|
SELECT test_setof_as_iterator(1, 'list');
|
|
SELECT test_setof_as_iterator(2, 'list');
|
|
SELECT test_setof_as_iterator(2, null);
|
|
|
|
SELECT test_setof_spi_in_iterator();
|
|
|
|
|
|
-- setof function with an SPI result set (used to crash because of
|
|
-- memory management issues across multiple calls)
|
|
|
|
CREATE OR REPLACE FUNCTION get_user_records()
|
|
RETURNS SETOF users
|
|
AS $$
|
|
return plpy.execute("SELECT * FROM users ORDER BY username")
|
|
$$ LANGUAGE plpythonu;
|
|
|
|
SELECT get_user_records();
|