Het is ochtend hier aan de Far South Coast van NSW, en ik dacht dat ik hier nog eens een poging toe zou doen. Ik had eerder moeten vermelden dat onze implementatieomgeving RDS is, wat COPY minder aantrekkelijk maakt. Maar het idee om een array door te geven waarin elk element de rijgegevens bevat, is zeer aantrekkelijk. Het lijkt veel op een INSERT met meerdere waarden, maar met verschillende syntactische suikers. Ik heb een beetje naar arrays in Postgres geprikt en kom altijd verward weg door de syntaxis. Ik heb een paar echt uitstekende discussies gevonden met veel details van enkele topposters om te bestuderen:
https://dba.stackexchange .com/questions/224785/pass-array-of-mixed-type-into-stored-function
Van daaruit heb ik een werkende testfunctie:
DROP FUNCTION IF EXISTS data.item_insert_array (item[]);
CREATE OR REPLACE FUNCTION data.item_insert_array (data_in item[])
RETURNS int
AS $$
INSERT INTO item (
id,
marked_for_deletion,
name_)
SELECT
d.id,
d.marked_for_deletion,
d.name_
FROM unnest(data_in) d
ON CONFLICT(id) DO UPDATE SET
marked_for_deletion = EXCLUDED.marked_for_deletion,
name_ = EXCLUDED.name_;
SELECT cardinality(data_in); -- array_length() doesn't work. ¯\_(ツ)_/¯
$$ LANGUAGE sql;
ALTER FUNCTION data.item_insert_array(item[]) OWNER TO user_bender;
Om de cirkel te sluiten, is hier een voorbeeld van wat invoer:
select * from item_insert_array(
array[
('2f888809-2777-524b-abb7-13df413440f5',true,'Salad fork'),
('f2924dda-8e63-264b-be55-2f366d9c3caa',false,'Melon baller'),
('d9ecd18d-34fd-5548-90ea-0183a72de849',true,'Fondue fork')
]::item[]
);
Terugkomend op mijn testresultaten, deze presteert ongeveer net zo goed als mijn originele multi-value-insert. De andere twee methoden die ik oorspronkelijk heb gepost, zijn, laten we zeggen, 4x langzamer. (De resultaten zijn nogal grillig, maar ze zijn altijd een stuk langzamer.) Maar ik blijf met mijn oorspronkelijke vraag zitten:
Is deze injectie veilig?
Als dat niet het geval is, denk ik dat ik het in PL/pgSQL moet herschrijven met een FOREACH-lus en UITVOEREN... GEBRUIKEN of FORMATEREN om de functies voor het opschonen van tekstverwerking/interpolatie daar te krijgen. Weet iemand het?
Ik heb nog een heleboel andere vragen over deze functie (Moet het een procedure zijn om de transactie te kunnen beheren? Hoe kan ik de invoer willekeurig maken? Wat zou een verstandig resultaat zijn om terug te sturen?) Maar ik denk dat ik vervolg deze als hun eigen vragen.
Bedankt voor alle hulp!