Hallo,
ich starteg erade mit Postgres und bin durchweg begeistert.
Mein Traum, auch größere Dateien im Filesystem des Servers über den DB-Server zu lesen und zu schreiben schien auch mit einer Extension für Externe Files in Erfüllung zu gehen: https://github.com/darold/external_file. Leider hat diese ein paar Schwächen, die ich mit meinen aktuellen Kenntnissen nicht lösen kann:
- Files ab 1GB führen zu “out of memory”. Könnte man scheibchenweise schreiben und lesen? Wie würde das gehen?
- Schreiben klappt durchgängig bis zum “out of memory”.
- Ich gehe mit Delphi 10 Seattle und UniDac auf die Datenbank.
- Lesen hängt manchmal beim Open eines “select readefile(‘pfad’)” für ewige Zeit. Ich vermute, dass es an der Art und Weise liegt, wie da blockweise gelesen wird. Danach klappt es schnell aber unzuverlässig.
- Die Datenbank bläht soch dabei extrem auf. Kann man das Logging dafür unterbinden?
Ich habe das Teil schon etwas umgeschrieben, um direkt einen Pfad angeben zu können. Vielleicht kann jemand der Pros hier helfen, wie man das Ganze und vor allem die Readefile-Routine verbessern kann. Würde Postgres nochmal um ein wirklich cooles Feature ergänzen.
Danke!
Michael Schumann
CREATE OR REPLACE FUNCTION public.writeefile(
buffer bytea,
filename character varying)
RETURNS void AS
$BODY$
DECLARE
l_oid oid;
lfd integer;
lsize integer;
BEGIN
l_oid := lo_create(0);
lfd := lo_open(l_oid,131072); --0x00020000 write mode
lsize := lowrite(lfd,buffer);
PERFORM lo_close(lfd);
PERFORM lo_export(l_oid,filename);
PERFORM lo_unlink(l_oid);
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION public.writeefile(bytea, character varying)
OWNER TO itcms;
CREATE OR REPLACE FUNCTION public.readefile(filename character varying)
RETURNS bytea AS
$BODY$
DECLARE
l_oid oid;
r record;
buffer bytea;
BEGIN
buffer := '';
SELECT lo_import(filename) INTO l_oid;
FOR r IN ( SELECT data
FROM pg_largeobject
WHERE loid = l_oid
ORDER BY pageno ) LOOP
buffer = buffer || r.data;
END LOOP;
PERFORM lo_unlink(l_oid);
return buffer;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION public.readefile(character varying)
OWNER TO itcms;