4D v16Serviços baseados nos procedimentos armazenados (exemplo) |
||||||||||
|
4D v16
Serviços baseados nos procedimentos armazenados (exemplo)
|
Valor | Descrição |
1 | foi publicada a petição mas não foi processada. |
0 | foi processado com êxito a petição. |
< 0 | foi processada a petição mas ocorreu um erro. |
Nota: Estes valores são escolhidos arbitrariamente para este exemplo, não são impostos por 4D.
A comunicação entre um processo cliente e um procedimento armazenado pode ser implantado utilizando os comandos GET PROCESS VARIABLE, SET PROCESS VARIABLE e VARIABLE TO VARIABLE. Por exemplo, esta solução utilizada na seção Importação baseada nos procedimentos armazenados (exemplo), como também no método de projeto STOP SP SERVICES listado anteriormente.
Aqui, o sistema deve permitir ao procedimento armazenado receber e reenviar as quantidades das variáveis de dados. Pode utilizar arrays, incluindo arrays de texto e imagem), mas há duas razões principais para preferir o emprego de uma tabela:
O método de projeto Client post request é um método genérico para enviar uma petição:
` Método de projeto Client post request
` Client post request ( Cadeia { ; Texto } ) -> Inteiro longo
` Client post request ( Tipo de petição { ; Parâmetros } ) -> Número de petição
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
O método devolve o número da petição, cuja unicidade está garantida pelo uso do comando Sequence number. Uma vez adicionado o registro a tabela [SP Requests], o cliente não têm que interrogar regularmente o campo [SP Requets]redStatus até que o procedimento armazenado termine de processar a petição.
O método de projeto Client get result é um método genérico para provar o estado da petição. Como foi explicado anteriormente, logo como o campo [SP Requets]redStatus se torna diferente de 1, o cliente sabe que o procedimento armazenado foi tratado (com êxito ou não) a petição.
` Método de projeto Client get result
` Client get result ( Inteiro longo ; ->BLOB {; Inteiro longo } ) -> Inteiro longo
` Client get result ( Número de petição ; ->Dados {; Duração } ) -> Código do erro
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 perdeu o registro da petição
` Isto não deveria passar. Mas de todas formas estabelece o código de erro -2 (valor arbitrário)
$0:=-2
End if
` A petição ainda não foi processada
If($0=1)
WAITING LOOP($vlDelay)
End if
Until($0&NBSP;#&NBSP;1)
READ ONLY([SP Requests])
Se a petição foi administrada com êxito pelo procedimento armazenado, o método copia o resultado (se existe) do registro ao BLOB cujo ponteiro foi passado como parâmetro. O método chamado depois analisa e utiliza os dados do BLOB em função do tipo de pedido. Note que o cliente está encarregado de apagar o registro [SP Requests] uma vez termina o pedido.
O pequeno método de projeto WAITING LOOP faz um laço até um certo número de tics:
` Método de projeto WAITING LOOP
` WAITING LOOP ( Inteiro longo )
` WAITING LOOP ( Tempo em tics )
C_LONGINT($1)
$vlStartTicks:=Tickcount
Repeat
IDLE
Until((Tickcount-$vlStartTicks)>=$1)
Lembrança: DELAY PROCESS não tem efeito no processo principal. Se utiliza o método de projeto WAITING LOOP, o processo esperará a quantidade de tempo necessário, ainda que o pedido tenha origem desde o processo do ambiente usuário de uma máquina cliente.
O método de projeto SP SERVICES é o método executado como procedimento armazenado na máquina servidor. A estrutura geral deste método, a continuação, muito simples:
Inicialização de uma variável “stop”
Repetir
Pesquisa das petições cujo campo [SP Requests]reqStatus é igual a 1
Para cada petição
Em função do tipo de petição, chamar uma subrotina
que guarde o resultado no campo [SP Requests]reqData
Mudar o estado da petição para que o cliente saiba que passou
End for
“Dormir” um pouco antes de voltar a começar
Até que a variável “stop” se torne true
Este é o código fonte real:
` Método de projeto SP SERVICES
` O procedimento armazenado começa
vbStopSPServices:=False
` O procedimento armazenado não necessita acesso em leitura escritura as tabelas...
READ ONLY(*)
` ...exceto a tabela [SP Requests]
READ WRITE([SP Requests])
Repeat
` Pesquisa dos pedidos ainda não processados
QUERY([SP Requests];[SP Requests]reqStatus=1)
` Processo destas petições uma por uma
For($vlRecord;1;Records in selection([SP Requests]))
` Se o registro da petição está bloqueado, esperar até que esteja desbloqueado
While(Locked([SP Requests]))
` Esperar um segundo antes de tentar novamente
DELAY PROCESS(Current process;60)
` Trata de obter acesso leitura-escritura
LOAD RECORD([SP Requests])
End while
` Assume que a petição será processada com sucesso
[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)
` ...
` OUTROS TIPOS DE PETIÇÕES PODERIAM SER INCLUÍDAS AQUI
` ...
Else
` O tipo de petição é desconhecido, devolver o erro -1 (valor arbitrário)
[SP Requests]reqStatus:=-1
End case
` Forçar o estado da petição a outro diferente de 1
` (em caso de uma subrotina dar o valor 1)
If([SP Requests]reqStatus=1)
[SP Requests]reqStatus:=-3
End if
` Atualizar o registro da petição
SAVE RECORD([SP Requests])
` Ir a seguinte petição não processada
NEXT RECORD([SP Requests])
End for
` Liberar o último registro processado
UNLOAD RECORD([SP Requests])
` Espere um segundo antes de continuar respondendo petições
DELAY PROCESS(Current process;60)
` Bucle até que seja ordenado ao procedimento armazenado parar sua execução
Until(vbStopSPServices)
O método de projeto SP SERVICES pode ser utilizado como modelo para implementar serviços inovadores em uma base. Nesta seção, detalhamos as subrotinas SP DO SERVER INFORMATION e SP DO VOLUME LIST. A subrotina SP DO BROWSE DIRECTORY (que toma como parâmetro um parâmetro enviado pelo cliente no campo [SP Requests]reqParams) não se trata neste documento.
Dependendo do tipo da petição, o método de projeto SP SERVICES chama a uma subrotina cuja tarefa é guardar os dados resultantes no campo [SP Requests]reqData. O armazenamento do registro e a mudança do estado a realizar o método de projeto SP SERVICES.
Esta é a subrotina SP DO SERVER INFORMATION que guarda a informação relativa ao servidor no BLOB. Outro método de projeto extrairá os dados do BLOB em função da máquina cliente.
` Método de projeto 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 é a subrotina SP DO VOLUME LIST, que guarda a informação relativa aos volumes no BLOB. Outro método de projeto extrairá os dados do BLOB em função da máquina cliente.
` Método de projeto 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;*)
Com os métodos de projeto genéricos Client post request e Client get result, o método de projeto M_SERVER_INFORMATION mostra, na máquina cliente, a informação devolvida pelo procedimento armazenado. Este método pode estar associado a um comando de menu ou ser chamado, por exemplo, desde o método de objeto de um botão:
` M_SERVER_INFORMATION
C_BLOB(vxData)
C_LONGINT($vlReqID;$vlErrCode;$vlOffset)
` Envio do pedido
$vlReqID:=Client post request("Server Information")
` Prova do estado do pedido e recepção do resultado
$vlErrCode:=Client get result($vlReqID;->vxData;60)
` Caso o pedido termina com sucesso, é mostrado o resultado
If($vlErrCode=0)
` Extração da informação resultante do 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álises das propriedades da plataforma
vs4DPlatform:="Versão de 4D Server desconhecida"
vsSystem:="Versão do sistema desconhecida"
vsMachine:="Computador desconhecido"
`...
` Este é o código (não listado) que analisa $vlSystem e $vlMachine
` ( ver o exemplo do comando PLATFORM PROPERTIES)
` ...
` Visualização da informação resultante
DIALOG([SP Requests];"SERVER INFORMATION")
Else
ALERT("Erro de pedido "+String($vlErrCode))
End if
` Não é mais necessário o BLOB
CLEAR VARIABLE(vxData)
Este é o formulário [SP Requests];"SERVER INFORMATION" em execução:
Com os métodos de projeto genéricos Client post request e Client get result, o método de projeto M_SERVER_VOLUMES mostra, na máquina cliente, a informação na lista dos volumes do servidor devolvidos pelo procedimento armazenado. Este método pode estar associado a um comando de menu ou chamado, por exemplo, desde o método de objeto de um botão:
` M_SERVER_VOLUMES
C_BLOB(vxData)
` Envio do pedido
$vlReqID:=Client post request("Volume List")
` Prova do estado da petição e recepção do resultado
$vlErrCode:=Client get result($vlReqID;->vxData;120)
` Se a petição termina com sucesso, mostra o resultado
If($vlErrCode=0)
` Extração da informação resultante do 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))
` Conversão de bytes em MB
arVSize{$vlElem}:=arVSize{$vlElem}/1048576
arVUsedSpace{$vlElem}:=arVUsedSpace{$vlElem}/1048576
arVFreeSpace{$vlElem}:=arVFreeSpace{$vlElem}/1048576
End for
` Visualização da informação resultante
DIALOG([SP Requests];"VOLUME LIST")
Else
ALERT("Erro de petição "+String($vlErrCode))
End if
` Já não é necessário o BLOB
CLEAR VARIABLE(vxData)
Este é o formulário [SP Requests];"VOLUME LIST" em execução:
Importação baseada nos procedimentos armazenados (exemplo)
Procedimentos armazenados
Produto: 4D
Tema: 4D Server e a linguagem 4D
Manual de 4D Server ( 4D v16)