Pular para o conteúdo principal

Postagem em destaque

BlackTDN :: JSON Schema Validation: A Comprehensive Guide

# JSON Schema Validation: A Comprehensive Guide ## Understanding JSONSchemaValidator Ensuring the integrity and compliance of JSON data is crucial for modern applications. **JSONSchemaValidator** is a powerful class designed to validate JSON data against a specified JSON Schema. It provides robust methods to check types, patterns, numerical constraints, required properties, and both internal and external schema references. This guide breaks down the key features and functionalities of JSONSchemaValidator, making it easier for developers to implement schema validation effectively. 🔗 **GitHub Repository:** [JSONSchemaValidator](https://github.com/naldodj/naldodj-hb-jsonschema-validator) --- ## Key Features ✅ **Schema-Based Validation** – Ensures JSON data conforms to a predefined schema. ✅ **Error Handling & Logging** – Captures validation errors for debugging. ✅ **Fast Mode Support** – Stops validation upon detecting the first error. ✅ **Internal & External Reference ...

BlackTDN :: Tips & Tricks ~ ADVPL : Embedded SQL - Facilitador de queries

Segundo o TDN “Embedded SQL - Facilitador de queries” tem por objetivo “facilitar a escrita e leitura de queries” e, de fato, a leitura de um código em Embeddes SQL é muito melhor do que a concatenação de strings. Observe um exemplo simples para o MSSQL:

Query String
   1: #include "protheus.ch"
   2: #include "tbiconn.ch"
   3: #include "topconn.ch"
   4:  
   5: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p>
   6:  
   7: USER PROCEDURE NotSqlEmb()
   8:  
   9:     Local cQuery
  10:  
  11:     Local cCRLF        := CRLF
  12:     Local cAlias
  13:  
  14:     RpcSetType(3)
  15:     PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01"
  16:         
  17:         cAlias        := GetNextAlias()
  18:  
  19:         cQuery        := "SELECT" + cCRLF
  20:         cQuery        += "    TOP 10 SA1.*" + cCRLF
  21:         cQuery        += "FROM
  22:         cQuery        += "    " + RetSqlName("SA1") + " SA1 " + cCRLF
  23:         cQuery        += "WHERE" + cCRLF
  24:         cQuery        += "    SA1.D_E_L_E_T_ = ' '" + cCRLF
  25:  
  26:         TCQUERY ( cQuery ) ALIAS ( cAlias ) NEW
  27:  
  28:         (cAlias)->( dbCloseArea() )
  29:  
  30:     RESET ENVIRONMENT
  31:  
  32: Return( NIL )






Embedded SQL


   1: #include "protheus.ch"
   2: #include "tbiconn.ch"
   3:  
   4: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p>
   5:  
   6: USER PROCEDURE SqlEmb()
   7:  
   8:     Local cAlias
   9:  
  10:     RpcSetType(3)
  11:     PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01"
  12:  
  13:         cAlias    := GetNextAlias()
  14:  
  15:         BEGINSQL ALIAS cAlias
  16:             %noParser%
  17:             SELECT
  18:                 TOP 10 SA1.*
  19:             FROM
  20:                 %table:SA1% SA1
  21:             WHERE
  22:                 SA1.%notDel%
  23:         ENDSQL
  24:  
  25:         (cAlias)->( dbCloseArea() )
  26:  
  27:     RESET ENVIRONMENT
  28:  
  29: Return



Mas nem tudo são “flores” e Embedded SQL, às vezes, dificulta ao invés de facilitar.


Um dos problemas conhecidos com Embedded SQL é o processo de depuração do código. Não conseguimos obter a “Query” antes de sua execução. Ao contrário da “Query String”: que nos permite obter o conteúdo integral da “Query” antes de sua execução. Permitindo-nos testá-la. Os exemplos abaixo, onde forçamos o erro, demonstram claramente isso:







Query String : Depuração


   1: #include "protheus.ch"
   2: #include "tbiconn.ch"
   3: #include "topconn.ch"
   4:  
   5: #xtranslate USER PROCEDURE <p> => PROCEDURE U_<p>
   6:  
   7: USER PROCEDURE NotSqlEmb()
   8:  
   9:     Local cQuery
  10:  
  11:     Local cCRLF        := CRLF
  12:     Local cAlias
  13:  
  14:     RpcSetType(3)
  15:     PREPARE ENVIRONMENT EMPRESA "01" FILIAL "01"
  16:         
  17:         cAlias        := GetNextAlias()
  18:  
  19:         cQuery        := "SELECT" + cCRLF
  20:         cQuery        += "    TOP 10 A1.*" + cCRLF
  21:         cQuery        += "FROM
  22:         cQuery        += "    " + RetSqlName("SA1") + " SA1 " + cCRLF
  23:         cQuery        += "WHERE" + cCRLF
  24:         cQuery        += "    SA1.D_E_L_E_T_ = ' '" + cCRLF
  25:  
  26:         TCQUERY ( cQuery ) ALIAS ( cAlias ) NEW
  27:  
  28:         (cAlias)->( dbCloseArea() )
  29:  
  30:     RESET ENVIRONMENT
  31:  
  32: Return( NIL )

A linha 20 contém um erro e, durante o processo de depuração basta inserirmos um “Break Point” na linha 26 para obtermos o conteúdo integral da “Query”.








BlackTDN : Depuração Query StringPara depurar e obter a “Query String” antes de sua execução basta inserir um “Break Point” na  linha executável imediatamente posterior à finalização da montagem: No exemplo na linha 26 onde a “Query” seria executada.


Obteremos o conteúdo da variável cQuery arrastando-a para a aba“Comandos” ou, simplesmente, digitando-a.


BlackTDN  :: Depuração Query String : Comandos Agora basta copiar o conteúdo da query e depurá-lo usando o “Query Analizer” de sua preferência.

BlackTDN  :: Depuração Query String : ComandosPoderemos, opcionalmente, forçar a execução da “Query” usando a TCSqlExec(cQuery) e obter o erro a partir da TCSqlError().
 







Já para Embedded SQL isso não é possível. Uma vez que, logo após a montagem da “Query String” ENDSQL “força” a sua  execução gerando uma exceção e finalizando o processo.






BlackTDN : Depuração Embedded SQL Tentativa de Depuração em código Embedded SQL.

BlackTDN : Depuração Embedded SQL : Inspetor de ExceçãoQuando da ocorrência do erro a comunicação é encerrada.  



Para solucionar esse problema podemos usar o “Tratamento de Exceção” (que não resolve o fato da “Query String” sempre ser executada) mas nos permite obter o seu conteúdo logo após a execução.






powershell Momento PowerShell: Uma coisa interessante no PowerShell é a cláusa WhatIf que nos permite testar a sintaxe de um comando.






# PowerShell -WhatIf safety parameter
Clear-Host
Get-Childitem C:\SomeFile\*.txt -recurse | remove-Item –whatIf



Embedded SQL deveria ter algo parecido “NoExecute?”.


Seria interessante não só para facilitar a depuração mas para personalizar a escrita. Vamos imaginar que utilizaremos o retorno da consulta para criar uma tabela temporária e, sobre essa tabela totalizar valores usando uma outra consulta. Usando Embedded SQL isso não é possível uma vez que a “Query” sempre será executada e teremos que executa-la novamente, e novamente … Um desperdício.


[]s
иαldσ dj

Comentários

  1. Fala Dj Naldo! Parabéns pelo blog! Sempre com conteúdo muito interessante.
    Sobre a depuração de Embedded SQL, pode-se colocar um ponto de parada logo após a instrução EndSql e utilizar a função GetLastQuery()

    Ela retorna um array com a estrutura:
    [1] cAlias - Alias usado para abrir o Cursor.
    [2] cQuery - Query executada.
    [3] aCampos - Array de campos com critério de conversão especificados.
    [4] lNoParser - Caso .T., não foi utilizada ChangeQuery() na String original.
    [5] nTimeSpend - Tempo, em segundos, utilizado para a abertura do Cursor.

    Abraços!

    ResponderExcluir
  2. Rafael, boa noite.

    Desculpe falar, mas sua ideia só funciona se não houver erro na SQL. Fiz aqui de todo jeito, e a única forma foi usando a string mesmo. O sistema dá erro na linha endsql, o que impossibilita o retorno das variáveis pois a instrução não foi finalizada ainda.

    ResponderExcluir
  3. Naldo, gostaria de saber como eu posso implementar meu proprio embedded SQL parassando a query para uma classe que tenho que gera os dados da consulta em um objeto.

    Gostaria de saber como eu posso obter o codigo que ficaria entre o beginSQLTESTE ate o EndSQLTeste e executar ao fim e retornar o objeto com os dados que eu quero resultar!

    ResponderExcluir

Postar um comentário

Postagens mais visitadas