I\'m probably doing something wrong with forming the literal. Suppose I have a simple stored procedure like this:
CREATE OR REPLACE FUNCTION do_something(inp
Craig explained well a reason for this behave - Assignment variable=value inside FOR statement expects zero nesting. So you should to do:
CREATE OR REPLACE FUNCTION do_something(input_array composite_type[])
RETURNS SETOF text AS $BODY$
DECLARE
temp_var record;
BEGIN
-- unnesting
FOR temp_var IN SELECT (unnest(input_array)).*
LOOP
RETURN NEXT temp_var.message;
END LOOP;
RETURN;
END
$BODY$ LANGUAGE plpgsql;
or -- preferable - newer use SetReturnedFunction inside "column list"
CREATE OR REPLACE FUNCTION do_something(input_array composite_type[])
RETURNS SETOF text AS $BODY$
DECLARE
temp_var record;
BEGIN
-- SELECT FROM
FOR temp_var IN SELECT * FROM unnest(input_array)
LOOP
RETURN NEXT temp_var.message;
END LOOP;
RETURN;
END
$BODY$ LANGUAGE plpgsql;
How you specify your input appears fine, as the same behaviour is observed with row- and array-constructor syntax:
SELECT * FROM do_something( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
And:
SELECT ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[];
produces:
'{"(test,11.00)","(test2,22.00)"}'
If you add a:
RAISE NOTICE '!%!',temp_var;
inside the loop the output is:
NOTICE: !("(test,11.00)",)!
NOTICE: !("(test2,22.00)",)!
showing that you're actually getting a tuple with "message" as the tuple text you expected and a null "amount".
So. Why?
It's a bit of a subtle one. You're using:
SELECT unnest(input_array)
which seems to do what you want, right:
regress=> SELECT unnest( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
unnest
---------------
(test,11.00)
(test2,22.00)
(2 rows)
... but actually, it's returning a single column of type composite_type
. PL/PgSQL composite type assignment expects one column per type column instead. So the single col is being shoved into 'message' and there is no second col.
Instead, write:
SELECT * FROM unnest(input_array)
to unpack the composite for assignment. Then it works as expected:
regress=> SELECT * FROM do_something( ARRAY[ ROW('test',11), ROW('test2',22) ]::composite_type[] );
do_something
--------------
test
test2
(2 rows)
If the first field of composite_type
were of a non-text type, you'd get an error that was rather more informative about this.