Protocolo

Esta secci�n describe el flujo de mensajes. Existen cuatro tipos diferentes de flujo dependiendo del estado de la conexi�n: inicio, consulta, llamada de funci�n y final. Existen tambien provisiones especiales para notificaci�n de respuestas y cancelaci�n de comandos, que pueden ocurrir en cualquier instante despues de la fase de inicio.

Inicio

El inicio se divide en fase de autentificaci�n y fase de arranque del backend.

Inicialmente, el frontend env�a un StartupPacket. El postmaster utiliza esta informaci�n y el contenido del fichero pg_hba.conf(5) para determinar que m�todo de autentificaci�n debe emplear. El postmaster responde entonces con uno de los siguientes mensajes:

ErrorResponse

El postmaster cierra la comunicaci�n inmediatamente.

AuthenticationOk

El postmaster entonces cede la comunicaci�n al backend. El postmaster no toma parte en la comunicaci�n posteriormente.

AuthenticationKerberosV4

El frontend debe tomar parte en una di�logo de autentificaci�n Kerberos V4 (no descrito aqu�) con el postmaster. En caso de �xito, el postmaster responde con un AuthenticationOk, en caso contrario responde con un ErrorResponse.

AuthenticationKerberosV5

El frontend debe tomar parte en un di�logo de autentificaci�n Kerberos V5 (no descrito aqu�) con el postmaster. En caso de �xito, el postmaster responde con un AuthenticationOk, en otro caso responde con un ErrorResponse.

AuthenticationUnencryptedPassword

El frontend debe enviar un UnencryptedPasswordPacket. Si este es el password correcto, el postmaster responde con un AuthenticationOk, en caso contrario responde con un ErrorResponse.

AuthenticationEncryptedPassword

El frontend debe enviar un EncryptedPasswordPacket. Si este esel password correcto, el postmaster responde con un AuthenticationOk, en caso contrario responde con un ErrorResponse.

Si el frontend no soporta el m�todo de autentificaci�n requerido por el postmaster, deber�a cerrar inmediatamente la conexi�n.

Despues de enviar AuthenticationOk, el postmaster intenta lanzar un proceso backend. Como esto podr�a fallar, o el backend podr�a encontrar un error durante el arranque, el frontend debe esperar por una confirmaci�n de inicio correcto del backend. El frontend no deber�a enviar mensajes en este momento. Los posibles mensajes procedentes del backend durante esta fase son:

BackendKeyData

Este mensaje es enviado despues de un inicio correcto del backend. Proporciona una clave secreta que el frontend debe guardar is quiere ser capaz de enviar peticiones de cancelaci�n m�s tarde. El frontend no deber�a responder a este mensaje, pero podr�a continuar escuchando por un mensaje ReadyForQuery.

ReadyForQuery

El arranque del backend tuvo �xito. El frontend puede ahora enviar mensajes de peticiones o llamandas a funci�n.

ErrorResponse

El arranque del backend no tuvo �xito. La conexi�n es cerrada despues de enviar este mensaje.

NoticeResponse

Se env�a un mensaje de advertencia. El frontend deber�a mostrar un mensaje pero deber�a continuar a la espera de un mensaje ReadyForQuery o ErrorResponse.

El mensaje ReadyForQuery es el mismo que el backend debe enviar despues de cada ciclo de consulta. Dependiendo de las necesiades de codificado del frontend, es razonable considerar ReadyForQuery como iniciando un ciclo de consulta (y entonces BackendKeyData indica una conclusi�n correcta de la fase de inicio), o considerar ReadyForQuery como finalizando la fase de arranque y cada subsiguiente ciclo de consulta.

Consulta

Un ciclo de consulta se inicia por el frontend enviando un mensaje Query al backend. El backend entonces env�a uno o m�s mensajes de respuesta dependiendo del contenido de la cadea de consulta, y finalmente un mensaje ReadyForQuery. ReadyForQuery informa al frontend que puede enviar una nueva consulta o llamada de funci�n de forma segura.

Los posibles mensajes del backend son:

CompletedResponse

Una sentencia SQL se complet� con normalidad.

CopyInResponse

El backend est� preparado para copiar datos del frontend a una relaci�n. El frontend deber�a enviar entonces un mensaje CopyDataRows. El backend responde con un mensaje CompletedResponse con un tag de "COPY".

CopyOutResponse

El backend est� listo para copiar datos de una relaci�n al frontend. El env�a entonces un mensaje CopyDataRows, y un mensaje CompletedResponse con un tag de "COPY".

CursorResponse

La consulta fue bien un insert(l), delete(l), update(l), fetch(l) o una sentencia select(l). Si la transacci�n ha sido abortada entonces el backend env�a un mensaje CompletedResponse con un tag "*ABORT STATE*". En otro caso las siguientes respuesta son enviadas.

Para una sentencia insert(l), el backend env�a un mensaje CompletedResponse con un tag de "INSERT oid rows" donde rows es el n�mero de filas insertadas, y oid es el ID de objeto de la fila insertada si rows es 1, en otro caso oid es 0.

Para una sentencia delete(l), el backend env�a un mensaje CompletedResponse con un tag de "DELETE rows" donde rows es el n�mero de filas borradas.

Para una sentencia update(l) el backend env�a un mensaje CompletedResponse con un tag de "UPDATE rows" donde rows es el n�mero de filas modificadas.

para una sentencia fetch(l) o select(l), el backend env�a un mensaje RowDescription. Es seguido despu�s con un mensaje AsciiRow o BinaryRow (dependiendo de si fu� especificado un cursor binario) para cada fila que es env�ada al frontend. Por �ltimo, el backend env�a un mensaje CompletedResponse con un tag de "SELECT".

EmptyQueryResponse

Se encontro una caden de consulta vac�a. (La necesidad de distinguir este caso concreto es hist�rica).

ErrorResponse

Ocurri� un error.

ReadyForQuery

El procesado de la cadena de consulta se complet�. Un mensaje seperado es enviado para indicar esto debido a que la cadena de consulta puede contener m�ltiples sentencias SQL. (CompletedResponse marca el final el procesado del una sentencia SQL, no de toda la cadena). Siempre se enviar� ReadyForQuery, bien el procesado terminase con �xito o con error.

NoticeResponse

Un mensaje de advertencia fu� enviado en relaci�n con la consulta. Estas advertencias se env�an en adici�n a otras respuestas, es decir, el backend continuar� procesando la sentencia.

Un frontend debe estar preparado para aceptar mensaje ErrorResponse y NoticeResponse cuando se espere cualquier otro tipo de mensaje.

De hecho, es posible que NoticeResponse se reciba incluso cuando el frontned no est� esperando ning�n tipo de mensaje, es decir, cuando el backend est� normalmente inactivo. En particular, el frontend puede solicitar la finalizaci�n del backend. En este caso se env�a una NoticeResponse antes de cerrar la conexi�n. Se recomienda que el frontend compruebe esas advertencias as�ncronas antes de enviar cada sentencia.

Tambi�n, si el frontend env�a cualquier comando listen(l), entonces debe estar preparado para aceptar mensajes NotificationResponse en cualquier momento. V�ase m�s abajo.

Llamada a funci�n

Un ciclo de llamada a funci�n se inicia por el frontend enviando un mensaje FunctionCall al backend. El backend entonces env�a uno o m�s mensajes de respueste dependiendo de los resultados de la llamada a funci�n, y finalmente un mensaje ReadyForQuery. ReadyForQuery informa al frontend que puede enviar una nueva consulta o llamada a funci�n de forma segura.

Los posibles mensajes de respuesta provinientes de backend son:

ErrorResponse

Ocurri� un error.

FunctionResultResponse

La llamada a funci�n fue ejecutada y devolvi� un resultado.

FunctionVoidResponse

La llamada a funci�n fue ejecutada y no devolvi� resultados.

ReadyForQuery

El procesado de la llamada a funci�n se complet�. ReadyForQuery se enviar� siempre, aunque el procesado termine con �xito o error.

NoticeResponse

Un mensaje de advertencia se gener� en relaci�n con la llamada a funci�n. Estas advertencias aparecen en adici�n a otras respuestas, es decir, el backend continuar� procesando el comando.

El frontend debe estar preparado para aceptar mensajes ErrorResponse y NoticeResponse cuando se esperen otro tipo de mensajes. Tambi�n si env�a cualquier comando listen(l) debe estar preparado para aceptar mensajes NotificationResponse en cualquier momento, v�ase m�s abajo.

Respuestas de notificaci�n

Si un frontend env�a un comando listen(l), entonces el backend enviar� un mensaje NotificationResponse (no se confunca con NoticeResponse!) cuando un comando notify(l) sea ejecutado para el mismo nombre de notificaci�n.

Las respuestas de notificaci�n son permitidas en cualquier punto en el protocolo (despues del inicio), excepto dentro de otro mensaje del backend. As�, el frontend debe estar preparado para reconocer un mensaje NotificationResponse cuando est� esperando cualquier mensaje. De hecho deber�a ser capaz de manejar mensajes NotificationResponse incluso cuando no est� envuelto en una consulta.

NotificationResponse

Un comando notify(l) ha sido ejecutado para un nombre para el que se ejecut� previamente un comando listen(l). Se pueden enviar notifiaciones en cualquier momento.

Puede merecer la pena apuntar que los nombres utilizados en los comandos listen y notify no necesitan tener nada que ver con los nombres de relaciones (tablas) y bases de datos SQL. Los nombres de notificaci�n son simplemente nombres arbitrariamente seleccionados.

Cancelaci�n de peticiones en progreso

Durante el procesado de una consulta, el frontend puede solicitar la cancelaci�n de la consulta mediante el env�o de una peticion apropiada al postmaster. La petici�n de cancelaci�n no es enviada directamente al backend por razones de eficiencia de implementaci�n: no deseamos tener al backend constantemente esperando nuevos datos del frontend durante el procesado de consultas. Las peticiones de cancelaci�n deber�an ser relativamente infrecuentes, por lo que las hacemos un poco mas voluminosas con el f�n de evitar una penalizaci�n en el caso normal.

Para enviar una petici�n de cancelaci�n, el frontend abre una nueva conexi�n con el postmaster y env�a un mensaje CancelRequest, en vez del mensaje StartupPacket que enviar�a normalmente en una nueva conexi�n. El postmaster procesar� esta petici�n y cerrar� la conexi�n. Por razones de seguridad, no se env�a una respuesta directa al mensaje de cancelaci�n.

Un mensaje CancelRequest ser� ignorado a menos que contenga los mismos datos clave (PID y clave secreta) enviados al frontend durante el inicio de la conexi�n. Si la petici�n contiene el PID e clave secreta el backend aborta el procesado de la consulta actual.

La se�al de cancelaci�n puede tener o no tener efectos - por ejemplo, si llega despues de que el backend haya finalizado de procesar la petici�n, entonces no tendr� efecto. Si la cancelaci�n es efectiva, produce la terminaci�n prematura del comando actual dando un mensaje de error.

La consecuencia de todo esto es que por razones tanto de seguridad como de eficiencia, el frontend no tiene forma directa de decidir cuando una petici�n de cancelaci�n tuvo �xito. Debe continuar esperando hasta que el backend responda a al petici�n. Enviar unha petici�n de cancelaci�n simplemente aumenta las probabilidades de que la consulta actual finalice pronto, y aumenta las probabilidades de que falle con un mensaje de error en vez de terminar con �xito.

Ya que la petici�n de cancelaci�n es enviada al postmaster y no a trav�s del enlace normal frontend/backend, es posible que cualquier proceso realice la petici�n, no s�lo el frontend cuya consulta va a ser cancelada. Esto puede tener alg�n beneficio de cara a aumentar la flexibilidad al dise�ar aplicaciones multi-proceso. Tambien introduce un riesgo de seguridad, ya que personas no autorizadas podr�an intentar cancelar consultas. El riesgo de seguridad es afrontado requiriendo la clave secreta generada din�micamente.

Finalizaci�n

El procedimiento de finalizaci�n normal es que el frontend env�e un mensaje Terminate y cierre inmediatamente la conexi�n. Al recibir el mensaje, el backend cierra inmediatamente la conexi�n y finaliza.

Una finalizaci�n anormal puede ocurrir debido a fallos de software (i.e. core dump) en cualquier extremo. Si el frontend o el backend ve un cierre inexperado de la conexi�n, deber�a liberar resursos y finalizar. El frontend tiene la opci�n de lanzar un nuevo backen recontactando el postmaster, si lo desea.