Do not use CREATE TYPE to return a polymorphic result. Use the record type> instead . Check this:
CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$ DECLARE ret RECORD; BEGIN
Note that it can return two or three columns if necessary, depending on the input.
test=> SELECT test_ret('foo','barbaz'); test_ret ---------------------------------- (t,foobarbaz,"a shorter than b") (1 row) test=> SELECT test_ret('barbaz','foo'); test_ret ---------------------------------- (f,foobarbaz) (1 row)
This is detrimental to the code, so use a consistent number of columns, but it is ridiculously convenient for returning optional error messages with the first parameter returning the success of the operation. Rewritten using a consistent number of columns:
CREATE FUNCTION test_ret(a TEXT, b TEXT) RETURNS RECORD AS $$ DECLARE ret RECORD; BEGIN
Almost to the epic heat:
test=> SELECT test_ret('foobar','bar'); test_ret ---------------- (f,barfoobar,) (1 row) test=> SELECT test_ret('foo','barbaz'); test_ret ---------------------------------- (t,foobarbaz,"a shorter than b") (1 row)
But how do you split this into several lines so that your ORM selection can convert values to your own data type selection language? Heat:
test=> SELECT a, b, c FROM test_ret('foo','barbaz') AS (a BOOL, b TEXT, c TEXT); a | b | c ---+-----------+------------------ t | foobarbaz | a shorter than b (1 row) test=> SELECT a, b, c FROM test_ret('foobar','bar') AS (a BOOL, b TEXT, c TEXT); a | b | c ---+-----------+--- f | barfoobar | (1 row)
This is one of the coolest and most underused features in PostgreSQL. Please spread the word.