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]reqIDO 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 trueEste é 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)
Adicionar um comentário