Passing array of a composite type to stored procedure

前端 未结 2 1900
再見小時候
再見小時候 2020-12-19 20:26

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         


        
2条回答
  •  伪装坚强ぢ
    2020-12-19 20:32

    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.

提交回复
热议问题