| -- |
| -- Test returning tuples |
| -- |
| CREATE TABLE table_record ( |
| first text, |
| second int4 |
| ) ; |
| CREATE TYPE type_record AS ( |
| first text, |
| second int4 |
| ) ; |
| CREATE FUNCTION test_table_record_as(typ text, first text, second integer, retnull boolean) RETURNS table_record AS $$ |
| if retnull: |
| return None |
| if typ == 'dict': |
| return { 'first': first, 'second': second, 'additionalfield': 'must not cause trouble' } |
| elif typ == 'tuple': |
| return ( first, second ) |
| elif typ == 'list': |
| return [ first, second ] |
| elif typ == 'obj': |
| class type_record: pass |
| type_record.first = first |
| type_record.second = second |
| return type_record |
| $$ LANGUAGE plpython3u; |
| CREATE FUNCTION test_type_record_as(typ text, first text, second integer, retnull boolean) RETURNS type_record AS $$ |
| if retnull: |
| return None |
| if typ == 'dict': |
| return { 'first': first, 'second': second, 'additionalfield': 'must not cause trouble' } |
| elif typ == 'tuple': |
| return ( first, second ) |
| elif typ == 'list': |
| return [ first, second ] |
| elif typ == 'obj': |
| class type_record: pass |
| type_record.first = first |
| type_record.second = second |
| return type_record |
| elif typ == 'str': |
| return "('%s',%r)" % (first, second) |
| $$ LANGUAGE plpython3u; |
| CREATE FUNCTION test_in_out_params(first in text, second out text) AS $$ |
| return first + '_in_to_out'; |
| $$ LANGUAGE plpython3u; |
| CREATE FUNCTION test_in_out_params_multi(first in text, |
| second out text, third out text) AS $$ |
| return (first + '_record_in_to_out_1', first + '_record_in_to_out_2'); |
| $$ LANGUAGE plpython3u; |
| CREATE FUNCTION test_inout_params(first inout text) AS $$ |
| return first + '_inout'; |
| $$ LANGUAGE plpython3u; |
| -- Test tuple returning functions |
| SELECT * FROM test_table_record_as('dict', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('dict', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('dict', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('dict', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('dict', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('tuple', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('tuple', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('tuple', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('tuple', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('tuple', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('list', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('list', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('list', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('list', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('list', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('obj', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('obj', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('obj', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('obj', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_table_record_as('obj', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('dict', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('dict', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('dict', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('dict', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('dict', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('tuple', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('tuple', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('tuple', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('tuple', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('tuple', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('list', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('list', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('list', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('list', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('list', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('obj', null, null, false); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('obj', 'one', null, false); |
| first | second |
| -------+-------- |
| one | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('obj', null, 2, false); |
| first | second |
| -------+-------- |
| | 2 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('obj', 'three', 3, false); |
| first | second |
| -------+-------- |
| three | 3 |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('obj', null, null, true); |
| first | second |
| -------+-------- |
| | |
| (1 row) |
| |
| SELECT * FROM test_type_record_as('str', 'one', 1, false); |
| first | second |
| -------+-------- |
| 'one' | 1 |
| (1 row) |
| |
| SELECT * FROM test_in_out_params('test_in'); |
| second |
| ------------------- |
| test_in_in_to_out |
| (1 row) |
| |
| SELECT * FROM test_in_out_params_multi('test_in'); |
| second | third |
| ----------------------------+---------------------------- |
| test_in_record_in_to_out_1 | test_in_record_in_to_out_2 |
| (1 row) |
| |
| SELECT * FROM test_inout_params('test_in'); |
| first |
| --------------- |
| test_in_inout |
| (1 row) |
| |
| -- try changing the return types and call functions again |
| ALTER TABLE table_record DROP COLUMN first; |
| ALTER TABLE table_record DROP COLUMN second; |
| ALTER TABLE table_record ADD COLUMN first text; |
| ALTER TABLE table_record ADD COLUMN second int4; |
| SELECT * FROM test_table_record_as('obj', 'one', 1, false); |
| first | second |
| -------+-------- |
| one | 1 |
| (1 row) |
| |
| ALTER TYPE type_record DROP ATTRIBUTE first; |
| ALTER TYPE type_record DROP ATTRIBUTE second; |
| ALTER TYPE type_record ADD ATTRIBUTE first text; |
| ALTER TYPE type_record ADD ATTRIBUTE second int4; |
| SELECT * FROM test_type_record_as('obj', 'one', 1, false); |
| first | second |
| -------+-------- |
| one | 1 |
| (1 row) |
| |
| -- errors cases |
| CREATE FUNCTION test_type_record_error1() RETURNS type_record AS $$ |
| return { 'first': 'first' } |
| $$ LANGUAGE plpython3u; |
| SELECT * FROM test_type_record_error1(); |
| ERROR: key "second" not found in mapping |
| HINT: To return null in a column, add the value None to the mapping with the key named after the column. |
| CONTEXT: while creating return value |
| PL/Python function "test_type_record_error1" |
| CREATE FUNCTION test_type_record_error2() RETURNS type_record AS $$ |
| return [ 'first' ] |
| $$ LANGUAGE plpython3u; |
| SELECT * FROM test_type_record_error2(); |
| ERROR: length of returned sequence did not match number of columns in row |
| CONTEXT: while creating return value |
| PL/Python function "test_type_record_error2" |
| CREATE FUNCTION test_type_record_error3() RETURNS type_record AS $$ |
| class type_record: pass |
| type_record.first = 'first' |
| return type_record |
| $$ LANGUAGE plpython3u; |
| SELECT * FROM test_type_record_error3(); |
| ERROR: attribute "second" does not exist in Python object |
| HINT: To return null in a column, let the returned object have an attribute named after column with value None. |
| CONTEXT: while creating return value |
| PL/Python function "test_type_record_error3" |
| CREATE FUNCTION test_type_record_error4() RETURNS type_record AS $$ |
| return 'foo' |
| $$ LANGUAGE plpython3u; |
| SELECT * FROM test_type_record_error4(); |
| ERROR: malformed record literal: "foo" |
| DETAIL: Missing left parenthesis. |
| CONTEXT: while creating return value |
| PL/Python function "test_type_record_error4" |