Interfaces

Las herramientas que Postgres proporciona para acceder a los objetos grandes, tanto en el backend como parte de funciones definidas por el usuario como en el frontend como parte de una aplicación que utiliza la interfaz, se describen más abajo. Para los usuarios familiarizados con Postgres 4.2, PostgreSQL tiene un nuevo conjunto de funciones que proporcionan una interfaz más coherente.

Nota: Toda manipulación de objetos grandes debe ocurrir dentro de una transacción SQL. Este requerimiento es obligatorio a partir de Postgres v6.5, a pesar que en versiones anteriores era un requerimiento implícito, e ignorarlo resultará en un comportamiento impredecible.

La interfaz de objetos grandes en Postgres está diseñada en forma parecida a la interfaz del sistema de archivos de Unix, con funciones análogas como open(2), read(2), write(2), lseek(2), etc. Las funciones de usuario llaman a estas rutinas para obtener sólo los datos de interés de un objeto grande. Por ejemplo, si existe un tipo de objeto grande llamado foto_sorpresa que almacena fotografías de caras, entonces puede definirse una función llamada barba sobre los datos de foto_sorpresa. Barba puede mirar el tercio inferior de una fotografía, y determinar el color de la barba que aparece, si es que hubiera. El contenido total del objeto grande no necesita ser puesto en un búfer, ni siquiera examinado por la función barba. Los objetos grandes pueden ser accedidos desde funciones C cargadas dinámicamente o programas clientes de bases de datos enlazados con la librería. Postgres proporciona un conjunto de rutinas que soportan la apertura, lectura, escritura, cierre y posicionamiento en objetos grandes.

Creando un Objeto Grande

La rutina

Oid lo_creat(PGconn *conexion, int modo)
crea un nuevo objeto grande. modo es una máscara de bits que describe distintos atributos del nuevo objeto. Las constantes simbólicas listadas aquí se encuentran definidas en $PGROOT/src/backend/libpq/libpq-fs.h. El tipo de acceso (lectura, escritura, o ambos) se controla efectuando una operación OR entre los bits INV_READ (lectura) e INV_WRITE (escritura). Si el objeto grande debe archivarse -- es decir, si versiones históricas del mismo deben moverse periódicamente a una tabla de archivo especial -- entonces el bit INV_ARCHIVE debe utilizarse. Los dieciséis bits de orden bajo de la máscara constituyen el número de manejador de almacenamiento donde debe residir el objeto grande. Para otros sitios que no sean Berkeley, estos bits deberán estar siempre en cero. Los comandos indicados más abajo crean un objeto grande (invertido):
inv_oid = lo_creat(INV_READ|INV_WRITE|INV_ARCHIVE);
     

Importando un Objeto Grande

Para importar un archivo de UNIX como un objeto grande, puede llamar a la función

Oid lo_import(PGconn *conexion, const char *nombre_de_archivo)
nombre_de_archivo especifica la ruta y el nombre del archivo Unix que será importado como objeto grande.

Exportando un Objeto Grande

Para exportar un objeto grande dentro de un archivo de UNIX, puede llamar a la función

int lo_export(PGconn *conexion, Oid lobjId, const char *nombre_de_archivo)
El argumento lobjId especifica el Oid del objeto grande a exportar y el argumento nombre_de_archivo indica la ruta y nombre del archivo UNIX.

Abriendo un Objeto Grande Existente

Para abrir un objeto grande existente, llame a la función

int lo_open(PGconn *conexion, Oid lobjId, int modo)
El argumento lobjId especifica el Oid del objeto grande que se abrirá. Los bits de modo controlan si el objeto se abre para lectura (INV_READ), escritura o ambos. Un objeto grande no puede abrirse antes de crearse. lo_open devuelve un descriptor de objeto grande para su uso posterior en lo_read, lo_write, lo_lseek, lo_tell, y lo_close.

Escribiendo Datos en un Objeto Grande

La rutina

int lo_write(PGconn *conexion, int fd, const char *buf, size_t largo)
escribe largo bytes desde buf al objeto grande fd. El argumento fd debió ser previamente devuelto por una llamada a lo_open. Devuelve el número de bytes escritos efectivamente. En caso de error, el valor de retorno es negativo.

Leyendo Datos desde un Objeto Grande

La rutina

int lo_read(PGconn *conexion, int fd, char *buf, size_t largo)
lee largo bytes desde el objeto grande fd a buf. El argumento fd debió ser previamente devuelto por una llamada a lo_open. Devuelve el número de bytes leídos efectivamente. En caso de error, el valor de retorno es negativo.

Posicionándose en un Objeto Grande

Para cambiar la ubicación actual de lectura o escritura en un objeto grande, utilice la función

int lo_lseek(PGconn *conexion, int fd, int desplazamiento, int desde_donde)
Esta rutina mueve el puntero de posición actual para el objeto grande descripto por fd a la nueva ubicación especificada por el desplazamiento. Los valores válidos para desde_donde son SEEK_SET, SEEK_CUR, y SEEK_END.

Cerrando un Descriptor de Objeto Grande

Un objeto grande puede cerrarse llamando a

int lo_close(PGconn *conexion, int fd)
donde fd es un descriptor de objeto grande devuelto por lo_open. Si hay éxito, lo_close devuelve cero. Si hay un error, el valor devuelto es negativo.