Este es el sitio web histórico de la documentación de 4D. La documentación se está trasladando progresivamente a developer.4d.com |
||||||||||
|
4D v20 R7
Servicios basados en los procedimientos almacenados (ejemplo)
|
Valor | Descripción |
1 | se publicó la petición pero no se ha procesado. |
0 | se ha procesado con éxito la petición. |
< 0 | se procesó la petición pero ocurrió un error. |
Nota: estos valores se eligen arbitrariamente para este ejemplo, no son impuestos por 4D.
La comunicación entre un proceso cliente y un procedimiento almacenado puede implementarse utilizando los comandos GET PROCESS VARIABLE, SET PROCESS VARIABLE y VARIABLE TO VARIABLE. Por ejemplo, esta solución utilizada en la sección Importación con procedimientos almacenados (ejemplo), como también en el método de proyecto STOP SP SERVICES listado anteriormente.
Acá, el sistema debe permitir al procedimiento almacenado recibir y reenviar las cantidades variables de datos. Puede utilizar arrays, incluyendo arrays de texto e imagen), pero hay dos razones principales para preferir el empleo de una tabla:
El método de proyecto Client post request es un método genérico para enviar una petición:
` Método de proyecto Client post request
` Client post request ( Cadena { ; Texto } ) -> Entero largo
` Client post request ( Tipo de petición { ; Parámetros } ) -> Número de petición
CREATE RECORD([SP Requests])
[SP Requests]reqID:=Sequence number([SP Requests])
[SP Requests]reqType:=$1
[SP Requests]reqStatus:=1
If(Count parameters>=2)
[SP Requests]reqParams:=$2
End if
SAVE RECORD([SP Requests])
$0:=[SP Requests]reqID
El método devuelve el número de la petición, cuya unicidad está garantizada por el uso del comando Sequence number. Una vez añadido el registro a la tabla [SP Requests], el cliente no tiene que interrogar regularmente el campo [SP Requets]redStatus hasta que el procedimiento almacenado termine de procesar la petición.
El método de proyecto Client get result es un método genérico para probar el estado de la petición. Como se explicó anteriormente, tan pronto como el campo [SP Requets]redStatus se vuelve diferente de 1, el cliente sabe que el procedimiento almacenado ha tratado (con éxito o no) la petición.
` Método de proyecto Client get result
` Client get result ( Entero largo ; ->BLOB {; Entero largo } ) -> Entero largo
` Client get result ( Número de petición ; ->Datos {; Duración } ) -> Código del error
C_LONGINT($0;$1;$vlDelay)
$0:=1
$vlDelay:=0
If(Count parameters>=3)
$vlDelay:=$3
End if
READ ONLY([SP Requests])
Repeat
QUERY([SP Requests];[SP Requests]reqID=$1)
If(Records in selection([SP Requests])>0)
If([SP Requests]reqStatus&NBSP;#&NBSP;1)
$2->:=[SP Requests]reqData
READ WRITE([SP Requests])
While(Locked([SP Requests]))
WAITING LOOP($vlDelay)
LOAD RECORD([SP Requests])
End while
DELETE RECORD([SP Requests])
$0:=[SP Requests]reqStatus
End if
Else
` Se perdió el registro de la petición
` Esto no debería suceder. Pero de todas formas establece el código de error -2 (valor arbitrario)
$0:=-2
End if
` La petición aún no ha sido procesada
If($0=1)
WAITING LOOP($vlDelay)
End if
Until($0&NBSP;#&NBSP;1)
READ ONLY([SP Requests])
Si la petición fue administrada con éxito por el procedimiento almacenado, el método copia el resultado (si lo hay) del registro al BLOB cuyo puntero se pasó como parámetro. El método llamante luego analiza y utiliza los datos del BLOB en función del tipo de petición. Note que el cliente está encargado de borrar el registro [SP Requests] una vez termina la petición.
El pequeño método de proyecto WAITING LOOP hace un bucle hasta un cierto número de tics:
` Método de proyecto WAITING LOOP
` WAITING LOOP ( Entero largo )
` WAITING LOOP ( Duración en tics )
C_LONGINT($1)
$vlStartTicks:=Tickcount
Repeat
IDLE
Until((Tickcount-$vlStartTicks)>=$1)
Recordatorio: DELAY PROCESS no tiene efecto en el proceso principal. Si utiliza el método de proyecto WAITING LOOP, el proceso esperará la cantidad de tiempo necesaria, aunque la petición se origine desde el proceso del entorno usuario de un equipo cliente.
El método de proyecto SP SERVICES es el método ejecutado como procedimiento almacenado en el equipo servidor. La estructura general de este método, a continuación, es muy simple:
Inicialización de una variable “stop”
Repetir
Búsqueda de las peticiones cuyo campo [SP Requests]reqStatus es igual a 1
Para cada petición
En función del tipo de petición, llamar una subrutina
que guarde el resultado en el campo [SP Requests]reqData
Cambiar el estado de la petición para que el cliente sepa lo que sucedió
End for
“Dormir” un poco antes de volver a comenzar
Hasta que la variable “stop” se vuelva true
Este es el código fuente real:
` Método de proyecto SP SERVICES
` El procedimiento almacenado comienza
vbStopSPServices:=False
` El procedimiento almacenado no necesita acceso en lectura escritura a las tablas...
READ ONLY(*)
` ...excepto la tabla [SP Requests]
READ WRITE([SP Requests])
Repeat
` Búsqueda de las peticiones no procesadas aún
QUERY([SP Requests];[SP Requests]reqStatus=1)
` Proceso de estas peticiones una por una
For($vlRecord;1;Records in selection([SP Requests]))
` Si el registro de la petición está bloqueado, esperar hasta que esté desbloqueado
While(Locked([SP Requests]))
` Espera un segundo antes de intentar nuevamente
DELAY PROCESS(Current process;60)
` Trata de obtener acceso lectura-escritura
LOAD RECORD([SP Requests])
End while
` Asume que la petición se procesará con éxito
[SP Requests]reqStatus:=0
Case of
:([SP Requests]reqType="Server Information")
SP DO SERVER INFORMATION
:([SP Requests]reqType="Volume List")
SP DO VOLUME LIST
:([SP Requests]reqType="Browse Directory")
SP DO BROWSE DIRECTORY([SP Requests]reqParams)
` ...
` OTROS TIPOS DE PETICIONES PODRÍAN AÑADIRSE AQUÍ
` ...
Else
` El tipo de petición es desconocido, devolver el error -1 (valor arbitrario)
[SP Requests]reqStatus:=-1
End case
` Forzar el estado de la petición a otro diferente de 1
` (en caso de una subrutina dar el valor 1)
If([SP Requests]reqStatus=1)
[SP Requests]reqStatus:=-3
End if
` Actualizar el registro de la petición
SAVE RECORD([SP Requests])
` Ir a la siguiente petición no procesada
NEXT RECORD([SP Requests])
End for
` Liberar el último registro procesado
UNLOAD RECORD([SP Requests])
` Espere un segundo antes de continuar respondiendo peticiones
DELAY PROCESS(Current process;60)
` Bucle hasta que se le ordene al procedimiento almacenado detener su ejecución
Until(vbStopSPServices)
El método de proyecto SP SERVICES puede utilizarse como modelo para implementar novedosos servicios en una base. En esta sección, detallamos las subrutinas SP DO SERVER INFORMATION y SP DO VOLUME LIST. La subrutina SP DO BROWSE DIRECTORY (que toma como parámetro un parámetro enviado por el cliente en el campo [SP Requests]reqParams) no se trata en este documento.
Dependiendo del tipo de la petición, el método de proyecto SP SERVICES llama a una subrutina cuya tarea es guardar los datos resultantes en el campo [SP Requests]reqData. El almacenamiento del registro y el cambio del estado lo realizar el método de proyecto SP SERVICES.
Esta es la subrutina SP DO SERVER INFORMATION que guarda la información relativa al servidor en el BLOB. Otro método de proyecto extraerá los datos del BLOB en función del equipo cliente.
` Método de proyecto SP DO SERVER INFORMATION
TEXT TO BLOB(Application version(*);[SP Requests]reqData;UTF8 C string)
TEXT TO BLOB(Structure file;[SP Requests]reqData;UTF8 C string;*)
TEXT TO BLOB(Data file;[SP Requests]reqData;UTF8 C string;*)
PLATFORM PROPERTIES($vlPlatform;$vlSystem;$vlMachine)
VARIABLE TO BLOB($vlPlatform;[SP Requests]reqData;*)
VARIABLE TO BLOB($vlSystem;[SP Requests]reqData;*)
VARIABLE TO BLOB($vlMachine;[SP Requests]reqData;*)
Esta es la subrutina SP DO VOLUME LIST, que guarda la información relativa a los volúmenes en el BLOB. Otro método de proyecto extraerá los datos del BLOB en función del equipo cliente.
` Método de proyecto SP DO VOLUME LIST
VOLUME LIST($asVName)
$vlSize:=Size of array($asVName)
ARRAY REAL($arVSize;$vlSize)
ARRAY REAL($arVUsedSpace;$vlSize)
ARRAY REAL($arVFreeSpace;$vlSize)
For($vlElem;1;$vlSize)
VOLUME ATTRIBUTES($asVName{$vlElem};$arVSize{$vlElem};$arVUsedSpace{$vlElem}
;$arVFreeSpace{$vlELem})
End for
VARIABLE TO BLOB($asVName;[SP Requests]reqData)
VARIABLE TO BLOB($arVSize;[SP Requests]reqData;*)
VARIABLE TO BLOB($arVUsedSpace;[SP Requests]reqData;*)
VARIABLE TO BLOB($arVFreeSpace;[SP Requests]reqData;*)
Con los métodos de proyecto genéricos Client post request y Client get result, el método de proyecto M_SERVER_INFORMATION muestra, en el equipo cliente, la información devuelta por el procedimiento almacenado. Este método puede estar asociado a un comando de menú o ser llamado, por ejemplo, desde el método de objeto de un botón:
` M_SERVER_INFORMATION
C_BLOB(vxData)
C_LONGINT($vlReqID;$vlErrCode;$vlOffset)
` Envío de la petición
$vlReqID:=Client post request("Server Information")
` Prueba del estado de la petición y recepción del resultado
$vlErrCode:=Client get result($vlReqID;->vxData;60)
` Si la petición termina con éxito, muestra el resultado
If($vlErrCode=0)
` Extracción de la información resultante del BLOB
$vlOffset:=0
vsServerVersion:=BLOB to text(vxData;UTF8 C string;$vlOffset)
vsStructureFile:=BLOB to text(vxData;UTF8 C string;$vlOffset)
vsDataFile:=BLOB to text(vxData;UTF8 C string;$vlOffset)
BLOB TO VARIABLE(vxData;$vlPlatform;$vlOffset)
BLOB TO VARIABLE(vxData;$vlSystem;$vlOffset)
BLOB TO VARIABLE(vxData;$vlMachine;$vlOffset)
` Análisis de las propiedades de la plataforma
vs4DPlatform:="Versión de 4D Server desconocida"
vsSystem:="Versión del sistema desconocida"
vsMachine:="Equipo desconocido"
`...
` Este es el código (no listado) que analiza $vlSystem y $vlMachine
` ( ver el ejemplo del comando PLATFORM PROPERTIES)
` ...
` Visualización de la información resultante
DIALOG([SP Requests];"SERVER INFORMATION")
Else
ALERT("Error de petición "+String($vlErrCode))
End if
` Ya no se necesita el BLOB
CLEAR VARIABLE(vxData)
Este es el formulario [SP Requests];"SERVER INFORMATION" en ejecución:
Con los métodos de proyecto genéricos Client post request y Client get result, el método de proyecto M_SERVER_VOLUMES muestra, en el equipo cliente, la información en la lista de los volúmenes del servidor devuelta por el procedimiento almacenado. Este método puede estar asociado a un comando de menú o llamado, por ejemplo, desde el método de objeto de un botón:
` M_SERVER_VOLUMES
C_BLOB(vxData)
` Envío de la petición
$vlReqID:=Client post request("Volume List")
` Prueba del estado de la petición y recepción del resultado
$vlErrCode:=Client get result($vlReqID;->vxData;120)
` Si la petición termina con éxito, muestra el resultado
If($vlErrCode=0)
` Extracción de la información resultante del BLOB
$vlOffset:=0
BLOB TO VARIABLE(vxData;asVName;$vlOffset)
BLOB TO VARIABLE(vxData;arVSize;$vlOffset)
BLOB TO VARIABLE(vxData;arVUsedSpace;$vlOffset)
BLOB TO VARIABLE(vxData;arVFreeSpace;$vlOffset)
For($vlElem;1;Size of array(arVSize))
` Conversión de bytes en MB
arVSize{$vlElem}:=arVSize{$vlElem}/1048576
arVUsedSpace{$vlElem}:=arVUsedSpace{$vlElem}/1048576
arVFreeSpace{$vlElem}:=arVFreeSpace{$vlElem}/1048576
End for
` Visualización de la información resultante
DIALOG([SP Requests];"VOLUME LIST")
Else
ALERT("Error de petición "+String($vlErrCode))
End if
` Ya no es necesario el BLOB
CLEAR VARIABLE(vxData)
Este es el formulario [SP Requests];"VOLUME LIST" en ejecución:
Importación con procedimientos almacenados (ejemplo)
Procedimientos almacenados
Producto: 4D
Tema: 4D Server y el lenguaje 4D
Manual de 4D Server ( 4D v20 R7)