| 4D v13Serviços baseados nos procedimentos armazenados (exemplo) | ||||||||||
| 
 | 
    4D v13
 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:

	Produto: 4D
	Tema: 4D Server e a linguagem 4D
	
        
        
	
Importação baseada nos procedimentos armazenados (exemplo)
Procedimentos armazenados