Re: Copiar contenido de campo Blob

From: Gunnar Wolf <gwolf(at)gwolf(dot)org>
To: Norman Mauricio Garcia <normangarcia64(at)yahoo(dot)co(dot)uk>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Copiar contenido de campo Blob
Date: 2007-02-09 19:52:06
Message-ID: 20070209195206.GB25894@gwolf.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Norman Mauricio Garcia dijo [Fri, Feb 09, 2007 at 03:33:40PM +0000]:
> Saludos lista,
>
> Tengo una tabla con un campo de tipo large object (oid me sale en la
> definición de la tabla). Ahora, estoy interesado en crear una copia
> del campo en otro registro, me explico. Digamos que estoy guardando
> un archivo pdf, pero quiero crear una copia de manera que si el
> usuario elimina el registro o cambia el archivo pdf el original siga
> intacto.
>
> Se que puedo extraer el contenido del oid al sistema de archivos y
> volver a cargarlo a la base de datos con lo_import para crear un
> nuevo oid, pero me gustaría saber si existe una forma de hacerlo
> directamente con PostgreSql.

Hola,

Además de lo que los demás señalan, te sugiero considerar no usar
large objects referenciados por OIDs, sino que guardar tus datos en un
campo tipo bytea - No sólo su uso es más natural (directamente con tus
queridos select/insert/update/delete de toda la vida), sino que no
corres riesgos de perder espacio innecesario por usar un OID y perder
referencia a él. Además, usando campos estándar en una tabla, puedes
crear triggers para hacer esto que requieres. Claro, ten en
consideración que hacer manipulaciones como esta puede ser muy pesado,
especialmente si hablamos de archivos grandes. Imagina, pues, que
tengas:

CREATE TABLE documento (
id serial primary key,
titulo text NOT NULL,
filename text NOT NULL UNIQUE,
data bytea);

Antes que otra cosa, seguro te conviene indexar por nombre de archivo:

CREATE INDEX documento_filename ON documento(filename);

Y vas a mantener una tabla con una bitácora de cambios:

CREATE TABLE bitacora (
id serial primary key,
hora_cambio timestamp NOT NULL DEFAULT now(),
filename text NOT NULL,
operacion integer check (operacion >= 1 AND operacion <= 3),
old_data bytea
);

Nota que acá filename no es UNIQUE, pues un mismo archivo puede ser
eliminado o re-creado a lo largo del tiempo. Vamos a crear las funciones
- Aclaro: Estoy escribiendo directo al correo, puede que todo lo que
acá ponga esté plagado de errorres :) Pero la idea se mantiene. Estoy
empleando la horrible técnica de asignar valores (y por eso el check
de la operación) de un catálogo duro - Creación es 1, actualización 2,
remoción 3. Seguro puedes hacer algo más limpio ;-)

CREATE FUNCTION crea_doc_a_bitacora() RETURNS trigger AS
'BEGIN
INSERT INTO bitacora (filename, operacion) VALUES
(NEW.filename, 1);
END;' LANGUAGE 'plpgsql';
CREATE TRIGGER crea_doc_a_bitacora BEFORE INSERT ON documento
FOR EACH ROW EXECUTE PROCEDURE crea_doc_a_bitacora();

CREATE FUNCTION actualiza_doc_a_bitacora() RETURNS trigger AS
'BEGIN
INSERT INTO bitacora (filename, old_data, operacion) VALUES
(OLD.filename, OLD.data, 2);
END;' LANGUAGE 'plpgsql';
CREATE TRIGGER actualiza_doc_a_bitacora BEFORE INSERT ON documento
FOR EACH ROW EXECUTE PROCEDURE actualiza_doc_a_bitacora();

CREATE FUNCTION borra_doc_a_bitacora() RETURNS trigger AS
'BEGIN
INSERT INTO bitacora (filename, old_data, operacion) VALUES
(OLD.filename, OLD.data, 3);
END;' LANGUAGE 'plpgsql';
CREATE TRIGGER borra_doc_a_bitacora BEFORE INSERT ON documento
FOR EACH ROW EXECUTE PROCEDURE borra_doc_a_bitacora();

Espero que quede claro y -más aún- que sea útil :)

Saludos,

--
Gunnar Wolf - gwolf(at)gwolf(dot)org - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Jose Stragnari 2007-02-09 20:10:39 RE: Problema en ADO con campos text
Previous Message Jose Stragnari 2007-02-09 19:03:10 Problema en ADO con campos text