La funci�n PQexec es adecuada para emitir consultas en aplicaciones s�ncronas sencillas. Sin embargo, tiene una porci�n de definciencias importantes:
PQexec espera hasta que se completa la consulta. La aplicaci�n puede tener otro trabajo para hacer (como por ejemplo mantener una interfaz de usuario), en cuyo caso no se querr� bloquear esperando la respuesta.
Una vez que el control se pasa a PQexec, la aplicaci�n cliente tiene muy dificil intentar cancelar la consulta en curso. (Se puede hacer con un manipulador de se�ales, pero no de otra forma).
PQexec s�lo puede devolver una estructura PGresult. Si la cadena de la consulta emitida contiene m�ltiples comands SQL, se perder�n todos excepto el �ltimo.
Las aplicaciones que no se quieren encontrar con estas limitaciones, pueden utilizar en su lugar las funciones que subyacen bajo PQexec: PQsendQuery y PQgetResult.
Para los programas antiguos que utilizaban esta funcionalidad utilizando PQputline y PQputnbytes y esperaban bloqueados el env�o de datos del servidor, se a�adi� la funci�n PQsetnonblocking.
Las aplicaciones ant�guas pueden rechazar el uso de PQsetnonblocking y mantener el comportamiento anterior potencialmente bloquante. Los programas m�s nuevos pueden utilizar PQsetnonblocking para conseguir una conexi�n con el servidor completamente no bloqueante.
PQsetnonblocking fija el estado de la conexi�n a no bloqueante.
int PQsetnonblocking(PGconn *conn) |
Cuando una conexi�n a una base de datos se ha fijado como no bloqueante, y se llama a PQexec, se cambiar� el estado temporalmente a bloqueante, hasta que se completa la ejecuci�n de PQexec.
Se espera que en el pr�ximo futuro, la mayor�a de libp se haga segura para la funcionalida de PQsetnonblocking.
PQisnonblocking Devuelve la situaci�n de bloqueante o no de la conexi�n a la base de datos.
int PQisnonblocking(const PGconn *conn) |
PQsendQuery Env�a una consulta a Postgres sin esperar los resultados. Devuelve TRUE si la consulta se despach� correctamente, y FALSE si no fue as� (en cuyo caso, utilice PQerrorMessage para obtener m�s informaci�n sobre el fallo).
int PQsendQuery(PGconn *conn, const char *query); |
PQgetResult Espera el siguiente resultado de una ejecuci�n previa de PQsendQuery, y lo devuelve. Se devuelve NULL cuando la consulta est� completa y ya no habr� m�s resultados.
PGresult *PQgetResult(PGconn *conn); |
Utilizando PQsendQuery y PQgetResult se resuelve uno de los problemas de PQexec: Si una cadena de consulta contiene m�ltiples comandos SQL, los resultados de esos comandos se pueden obtener individualmente. (Esto permite una forma sencilla de procesamiento paralelo: la aplicaci�n cliente puede estar manipulando los resultados de una consulta mientras el servidor sigue trabajando sobre consultas posteriores de la misma cadena de consulta). Sin embargo, la llamada a PQgetResult seguir� probocando que el cliente quede bloqueado hasta que el servidor complete el siguiente comando SQL de la cadena. Esto se puede impedir con el uso adecuado de tres funciones m�s:
PQconsumeInput Si hay una entrada disponible desde el servidor, la recoge.
int PQconsumeInput(PGconn *conn); |
PQconsumeInput se puede llamar incluso si la aplicaci�n a�n no est� preparada para recibir un resultado o una notificaci�n. La rutina leer� los datos disponibles y los situar� en un almacenamiento intermedio, probocando as� una indicaci�n de preparado para leer a la funci�n select(2) para que contin�e. La aplicaci�n puede por ello utilizar PQconsumeInput para limpiar la condici�n select inmediatamente, y examinar despu�s los resultado tranquilamente.
PQisBusy Devuelve 1 si una consulta est� ocupada, es decir, si PQgetResult se quedar�a bloqueada esperando una entrada. Un 0 indica que se puede llamar a PQgetResult con la seguridad de no bloquear.
int PQisBusy(PGconn *conn); |
PQflush Intenta lanzar cualquier dato encolado al servidor, y devuelve 0 si lo consigue (o si la cola de env�o est� vac�a) y EOF si ha fallado por alg�n motivo.
int PQflush(PGconn *conn); |
PQsocket Obtiene el n�mero descriptor de fichero para el socket de conexi�n con el servidor. Un descriptor v�lido sera >= 0; un resultado de indica que no hay actualmente ninguna conexi�n con el servidor abierta.
int PQsocket(const PGconn *conn); |
Las conexi�nes no bloqueantes (que han utilizado PQsetnonblocking) no deber�an utilizar select hasta que PQflush haya devuelto 0 indicando que no quedan datos almacenados esperando ser enviados al servidor.
Una aplicaci�n cliente t�pica que utilice estas funciones tendr� un bucle principal que utiliza select(2) para esperar todas las condiciones a las que debe responder. Una de estas condiciones ser� la entrada disponible desde el servidor, lo que en terminos de select son datos legibles en el descriptor de fichero identificado por PQsocket. Cuando el bucle principal detecta que hay preparada una entrada, deber�a llamar a PQconsumeInput para leer la entrada. Puede despu�s llamar a PQisBusy, seguido de PQgetResult si PQisBusy devuelve falso (0). Puede llamar tambi�n a PQnotifies para detectar mensajes NOTIFY (ver "Notificaci�n As�ncrona", m�s abajo).
Una aplicaci�n cliente que utilice PQsendQuery/PQgetResult tambi�n puede intentar cancelar una consulta que a�n se est� procesando en el servidor.
PQrequestCancel Requiere de Postgres que abandone el procesado de la consulta actual.
int PQrequestCancel(PGconn *conn); |
N�tese que si la consulta forma parte de una transacci�n, la cancelaci�n abortar� la transacci�n completa.
PQrequestCancel se puede invocar de modo seguro desde un manipulador de se�ales. De esta forma, se puede utilizar en conjunci�n con PQexec plano, si la decisi�n de cancelar se puede tomar en un manipulador de se�ales. Por ejemplo, psql invoca a PQrequestCancel desde un manipulador de la se�al SIGINT, permitiendo de este modo la cancelaci�n interactiva de consultas que �l gestiona a trav�s de PQexec. Observese que PQrequestCancel no tendr� efecto si la conexi�n no est� abierta en ese momento, o si el servidor no est� procesando una consulta.