If that's the only type of call you expect, variadic
is just syntax noise. You can redefine your procedure to accept a regular array of type that fits into table events
, that you're trying to insert into. Also, you don't have to loop over a select from unnest()
- there's a FORACH
loop that lets you iterate over the array directly.
CREATE OR REPLACE PROCEDURE update_events ( events_array events[] )
LANGUAGE plpgsql AS $$
DECLARE
event_record events;
BEGIN
FOREACH event_record IN ARRAY events_array LOOP
INSERT INTO events
( metadata,
payload
)
VALUES
( event_record.metadata,
event_record.payload
);
END LOOP;
END; $$;
You can also insert directly from a select without any loop, gaining some performance from that and from switching to plain language SQL
that doesn't have the PLpgSQL overhead:
CREATE OR REPLACE PROCEDURE update_events ( events_array events[] )
LANGUAGE SQL AS $$
INSERT INTO events
( metadata,
payload
)
select
event_record.metadata,
event_record.payload
from unnest(events_array)
as event_record
( metadata,
payload
)
$$;
You can either cast each element in the array, or cast the whole array at once:
await client.query('CALL schema.function( ARRAY[$1]::events[] );', XXX);
Demo. If you happen to initially get a malformed record literal
error after these changes, it means that some or all of what you're supplying as XXX
isn't a valid set of values that can make up events
record. Another demo, showing some examples.
I'm naively assuming your events
table has only those two columns - if it has more, you'll have to define an intermediate type or table and use that as your array type in procedure definition and call argument cast. Example
In this case variadic
would be useful if you wanted to be able to use both types of calls below:
call update_events( --not an array in a strict sense, just a bunch of arguments
('metadata1','payload1')::events,
('metadata2','payload2')::events,
('metadata3','payload3')::events);
The above isn't passing an array in a strict sense, just a bunch of arguments that the function will internally collect and make available as a single, actual array.
call update_events( VARIADIC
ARRAY[('metadata1','payload1'),
('metadata2','payload2'),
('metadata3','payload3')
]::events[] );
VARIADIC
informs the function that nothing has to be collected into an array as the argument list is already provided as one.