El comando COPY en PostgreSQL tiene opciones para leer o escribir en la conexión de red utilizada para libpq. Por ello, se necesitan funciones para acceder a su conexión de red directamente, de forma que las aplicaciones puedan obtener ventajas de esta capacidad.
Estas funciones sólo se deberían utilizar tras obtener un objeto resultado PGRES_COPY_OUT o PGRES_COPY_IN a partir de PQexec o PQgetResult.
PQgetline Lee una línea de caracteres terminada con un caracter "newline" (transmitida por el servidor) en una cadena de almacenamiento de tamaño "length".
int PQgetline(PGconn *conn, char *string, int length) |
Observese que la aplicación deberá comprobar si la nueva línea consiste en los dos carácteres "\.", lo que indicaría que el servidor ha terminado de enviar los resultados del comando copy. Si la aplicación debería recibir líneas que son más largas de longitud-1, deberá tener cuidado de reconocer la línea "\." correctamente (y no confunde, por ejemplo, el final de una larga línea de datos con la línea de terminación). El código de src/bin/psql/copy.c contiene rutinas de ejemplo que manipulan correctamente el protocolo copy.
PQgetlineAsync Lee una línea de carácteres terminada con "newline" (transmitida por el servidor) en una zona de almacenamiento sin bloquear.
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize) |
La rutina devuelve -1 si reconoce el marcador end-of-copy-data, 0 si no tiene datos disponibles, o un número positivo que la el número de bytes de datos devueltos. Si se devuelve -1, la aplicación que realiza la llamada deberá llamar a PQendcopy, y volver después al procesado normal. Los datos devueltos no se extenderán más allá de un carácter "newline". Si es posible, se devolverá una línea completa cada vez. Pero si el almacenamiento ofrecido por la aplicación que realiza la llamada es demasiado pequeño para recibir una línea enviada por el servidor, se devolverán datos parciales. Se puede detectar esto comprobando si el último byte devuelto es "\n" o no. La cadena devuelta no se termina con un carácter nulo. (Si quiere usted añadir un NULL de terminación, asegurese de pasar una longitud del almacenamiento más pequeña que el tamaño del almacenamiento de que realmente dispone).
PQputline Envía una cadena terminada en carácter nulo al servidor. Devuelve 0 si todo funciona bien, y EOF si es incapaz de enviar la cadena.
int PQputline(PGconn *conn, const char *string); |
PQputnbytes Envía una cadena terminada en un carácter no nulo al servidor. Devuelve 0 si todo va bien, y EOF si es incapaz de enviar la cadena.
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes); |
PQendcopy Sincroniza con el servidor. Esta función espera hasta que el servidor ha terminado la copia. Debería utilizarse bien cuando se ha enviado la última cadena al servidor utilizando PQputline o cuando se ha recibido la última cadena desde el servidor utilizando PGgetline. Debe utilizarse, o el servidor puede recibir "out of sync (fuera de sincronía)" con el cliente. Una vez vuelve de esta función, el servidor está preparado para recibir la siguiente consulta. El valor devuelto es 0 si se completa con éxito, o diferente de cero en otro caso.
int PQendcopy(PGconn *conn); |
Como un ejemplo:
PQexec(conn, "create table foo (a int4, b char(16), d float8)"); PQexec(conn, "copy foo from stdin"); PQputline(conn, "3\thello world\t4.5\n"); PQputline(conn,"4\tgoodbye world\t7.11\n"); ... PQputline(conn,"\\.\n"); PQendcopy(conn); |
Cuando se está utilizando PQgetResult, la aplicación debería responder a un resultado PGRES_COPY_OUT ejecutando repetidamente PQgetline, seguido de PQendcopy una vez se detecta la línea de terminación. Debería entonces volver al bucle PQgetResult loop until hasta que PQgetResult devuelva NULL. Similarmente, un resultado PGRES_COPY_IN se procesa por una serie de llamadas a PQputline seguidas por PQendcopy, y volviendo entonces al bucle PQgetResult. Esta organización asegurará que un comando de copia de entrada o de salida embebido en una serie de comandos SQL se ejecutará correctamente.
Las aplicaciones antiguas habitualmente emiten una copia de entrada o de salida a través de PQexec y asumen que la transacción ha terminado tras el PQendcopy. Este mecanismo trabajará adecuadamente sólo si la copia de entrada/salida es el único comando SQL de la cadena de consulta.