Pesquisar

Artigo
· Fev. 11 3min de leitura

Uma visão sobre Dynamic SQL e Embededd SQL

 

 

Ao contrário do filme, citado através da imagem (para quem não conhece, Matrix, 1999), a escolha entre Dynamic SQL e Embededd SQL, não é uma escolha entre a verdade e a fantasia, mas, mesmo assim é uma decisão a ser tomada. Abaixo, tentarei facilitar a escolha de vocês.

Caso sua necessidade seja interações entre o cliente e a aplicação (consequentemente o banco de dados), o Dynamic SQL pode ser mais apropriado, pois “molda-se” muito facilmente com estas alterações de consultas. Entretanto, este dinamismo tem um custo, a cada consulta nova, ela é remodelada, podendo ter um custo maior para a execução. Abaixo um exemplo simples de um trecho de código Python.

Exemplo de SQL Dynamic

Apenas com base na informação acima, o Embededd SQL é a melhor escolha? Depende. Pensando única e exclusivamente em agilidade na execução, poderíamos partir para esta escolha. Uma vez que as instruções SQL são inseridas diretamente no código de programação, utilizando-se de variáveis HOST para entrada e saída de dados. O objetivo também não é ensinar como utilizar uma ou outra opção, e sim abrir a mente para possibilidade, conhecendo um pouco sobre cada um.

Abaixo, temos algumas características relevantes e que devem ser levadas em consideração quando iniciar um desenvolvimento que exija uma consulta SQL:

 Como já mencionado, o Embededd SQL é várias lembrado pelo seu desempenho, mas, isto não é uma corrida e nem só de velocidade se vive. Sua integração com diversas linguagens de alto nível, fazem com que os desenvolvedores possam utilizar os recursos de melhor forma, isto dá-se devido ao fato de não precisarem de tantas buscas em arquivos externos ou scripts separados, tornando o código mais limpo e sustentável.

É notado também pela sua consistência, afinal, alterações no banco de dados podem ser espelhadas no código SQL, evitando assim possíveis inconsistências nos dados. E por final, porém não menos importante, o fato das consultas estarem dentro do código, torna-o mais seguro, pois podem ser implementados controles de acesso diretamente no aplicativo, evitando assim acessos não autorizados e consultas indevidas.

Bom, agora podemos ver o que sustenta o Dynamic SQL. Este dinamismo é facilmente notado em sua flexibilidade, isto é, tudo é moldado enquanto está acontecendo, consultas, condições e até nomes de tabelas ou campos, beneficiando assim o cliente, o usuário. É marcado também pela facilidade de administração, uma vez que os DBAs conseguem realizar manutenções nos dados e bancos, conferindo em tempo real o impacto causado, evitando assim maiores problemas de compilação.

O resumo de toda esta informação, com mais teoria e pouca “prática” é que não há um lado certo ou um lado errado, até mesmo um vilão ou um mocinho, o fato é que o conhecimento sobre o que será desenvolvido, uma análise profunda das necessidades, levará a uma escolha...

De qual lado da força você estará?

2 Comments
Discussão (2)3
Entre ou crie uma conta para continuar
Artigo
· Fev. 11 2min de leitura

A look at Dynamic SQL and Embedded SQL

   

 

 

Unlike the movie mentioned in the image (for those who don't know, Matrix, 1999), the choice between Dynamic SQL and Embedded SQL is not a choice between truth and fantasy, but it is still a decision to be made. Below, I will try to make your choice easier. 

If your need is interactions between the client and the application (and consequently the database), Dynamic SQL may be more appropriate, as it "adapts" very easily to these query changes. However, this dynamism has a cost: with each new query, it is remodeled, which can have a higher cost to execute. Below is a simple example of a Python code snippet. 

Example of Dynamic SQL 

Based solely on the information above, is Embedded SQL the best choice? It depends. Thinking solely and exclusively about agility in execution, we could go for this choice. Since the SQL instructions are inserted directly into the programming code, using HOST variables for data input and output. The goal is not to teach how to use one or another option, but rather to open your mind to the possibilities, learning a little about each one. 

Below, we have some relevant features that should be taken into consideration when starting a development that requires an SQL query: 

As already mentioned, Embedded SQL is often remembered for its performance, but this is not a race and speed is not the only thing we live for. Its integration with several high-level languages ​​allows developers to use the resources in a better way, this is due to the fact that they do not need to search as many external files or separate scripts, making the code cleaner and more maintainable. 

It is also noted for its consistency, after all, changes to the database can be mirrored in the SQL code, thus avoiding possible inconsistencies in the data. And last but not least, the fact that the queries are within the code makes it more secure, since access controls can be implemented directly in the application, thus avoiding unauthorized access and inappropriate queries. 

Well, now we can see what supports Dynamic SQL. This dynamism is easily noticed in its flexibility, that is, everything is shaped as it happens, queries, conditions and even table or field names, thus benefiting the client, the user. It is also marked by ease of administration, since DBAs can perform maintenance on data and databases, checking the impact caused in real time, thus avoiding major compilation problems. 

The summary of all this information, with more theory and little “practice” is that there is no right or wrong side, not even a villain or a good guy, the fact is that knowledge about what will be developed, an in-depth analysis of needs, will lead to a choice... 

Which side of the force will you be on?

 
 
16 Comments
Discussão (16)6
Entre ou crie uma conta para continuar
Discussão (2)3
Entre ou crie uma conta para continuar
Artigo
· Fev. 11 7min de leitura

Generación de Especificaciones OpenAPI

Introducción

Una API REST (Representational State Transfer) es una interfaz que permite que diferentes aplicaciones se comuniquen entre sí a través del protocolo HTTP, utilizando operaciones estándar como GET, POST, PUT y DELETE. Las API REST son ampliamente utilizadas en el desarrollo de software para exponer servicios accesibles por otras aplicaciones, permitiendo la integración entre diferentes sistemas.

Sin embargo, para garantizar que las API sean fáciles de comprender y utilizar, es fundamental contar con una buena documentación. Aquí es donde entra en juego OpenAPI.

OpenAPI es un estándar para la descripción de API RESTful. Permite definir de manera estructurada el funcionamiento de una API, especificando los endpoints disponibles, los tipos de datos aceptados y devueltos, los parámetros requeridos y las respuestas esperadas. Toda esta información se recopila en un archivo de especificación (generalmente con extensión .yaml o .json), que puede ser interpretado por herramientas automáticas para generar código, documentación y más.

La especificación OpenAPI está diseñada para ser legible tanto por máquinas como por humanos, permitiendo describir, producir, consumir y visualizar servicios web RESTful de manera estandarizada. Por lo tanto, un documento OpenAPI representa una descripción formal de la API, útil tanto para los desarrolladores que necesitan utilizarla como para las herramientas que pueden aprovecharla para automatizar diversos procesos.

¿Por qué es útil definir un archivo de especificación?

Adoptar OpenAPI para documentar una API ofrece varios beneficios:

  • Claridad: Proporciona una documentación detallada y estructurada, permitiendo a los desarrolladores comprender rápidamente cómo interactuar con la API, qué solicitudes enviar y qué datos esperar en la respuesta.
  • Automatización: La documentación puede generarse automáticamente a partir del código, manteniéndose siempre actualizada con los cambios en la API.
  • Interactividad: Existen herramientas como Swagger, un conjunto de soluciones de código abierto para la documentación y prueba de API REST, que incluyen Swagger UI. Esta permite explorar y probar las API directamente desde el navegador, simplificando el desarrollo, la verificación y la comprensión de las API.
  • Estandarización: Al utilizar OpenAPI, la documentación sigue un formato compartido y reconocido, facilitando la integración con otras herramientas y servicios.

 

¿Cómo se puede generar un documento OpenAPI?

Existen dos enfoques principales para generar un archivo de especificación OpenAPI:

  • Enfoque "Code-first" (automático): Si ya se ha desarrollado una API REST en InterSystems IRIS, se puede generar automáticamente la documentación OpenAPI sin necesidad de escribir manualmente el archivo de especificación. IRIS ofrece una funcionalidad integrada que permite exportar la documentación OpenAPI en formato JSON o YAML, basándose en las definiciones de las clases REST.
  • Enfoque "Specification-first" (manual): En este caso, el archivo OpenAPI se escribe manualmente en YAML o JSON, describiendo todos los endpoints, parámetros y respuestas esperadas. Este enfoque es útil cuando se desea definir la API antes de implementarla, facilitando su diseño y la comunicación con otros desarrolladores o partes interesadas.

 

Enfoque Automático

Existen dos formas de generar automáticamente el archivo de especificación OpenAPI en InterSystems IRIS.

Método 1: Usando la función GetWebRESTApplication

Un enfoque es utilizar la función GetWebRESTApplication proporcionada por la clase %REST.API.
Un ejemplo práctico de cómo utilizarla es agregando la siguiente función en la clase de dispatch:

ClassMethod GenerateOpenAPI() As %Status
{
    // The name of the REST application
    Set webApplication = "MyAPP"  // Replace with the name of your web app
    // Retrieve the OpenAPI 2.0 documentation
    Set sc = ##class(%REST.API).GetWebRESTApplication("", webApplication, .swagger)
    
    If $$$ISERR(sc) {
        Quit sc  // If an error occurred, exit the method
    }
    
    // Return the documentation in JSON format
    Set %response.ContentType = "application/json"
    Do ##class(OMRREST.impl).%WriteResponse(swagger.%ToJSON()) 

    Quit $$$OK
}

Además, agrega la siguiente ruta a la UrlMap:

  <Route Url="/openapi" Method="GET" Call="GenerateOpenAPI"/>

En este punto, tendrás todo lo necesario para generar el archivo de especificación desde tu clase de dispatch. Para visualizar la documentación, conéctate a la URL indicada (donde MyWebapp es el nombre de tu aplicación web, tal como está definida en el portal de administración):

<host>:<port>/MyWebapp/openapi

El JSON generado de esta manera representa la especificación OpenAPI de tu API. Después de explorar el segundo método, veremos cómo visualizarlo y probarlo en Swagger.

Método 2: Usando la API de Gestión

Otra forma de generar el archivo de especificación OpenAPI es utilizando la API de Gestión de InterSystems IRIS.

Para llamar a este servicio, puedes usar herramientas como Postman, que es una herramienta para desarrolladores que permite probar, documentar y automatizar APIs.
Postman proporciona una interfaz simple e intuitiva para enviar solicitudes HTTP (GET, POST, PUT, DELETE, etc.), ver respuestas, gestionar autenticaciones y crear pruebas automatizadas.

Para realizar la solicitud utilizando Postman, sigue estos pasos:

  1. Haz clic en el botón New y crea una solicitud HTTP.
  2. Configura la solicitud de la siguiente manera y envíala:
    • Selecciona GET como el método HTTP.
    • Especifica la URL en el siguiente formato, utilizando el <baseURL> de tu instancia:
      https://<baseURL>/api/mgmnt/v1/namespace/myapp
      Aquí, namespace es el nombre del espacio de nombres donde has creado el servicio REST, y myapp es el nombre de tu aplicación web.
    • Configura el método de autorización como Basic Auth y proporciona el nombre de usuario y la contraseña de un usuario con acceso de lectura al espacio de nombres especificado.

Una vez que se genere el JSON, se podrá visualizar y probar utilizando herramientas como Swagger Editor.

{
   "info":{
      "title":"",
      "description":"",
      "version":"",
      "x-ISC_Namespace":"MyNamespace"
   },
   "basePath":"/MyWebapp",
   "paths":{
      "/loginForm":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"loginForm",
            "x-ISC_ServiceMethod":"loginForm",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/refresh":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"refresh",
            "x-ISC_ServiceMethod":"refresh",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/logout":{
         "post":{
            "parameters":[
               {
                  "name":"payloadBody",
                  "in":"body",
                  "description":"Request body contents",
                  "required":false,
                  "schema":{
                     "type":"string"
                  }
               }
            ],
            "operationId":"logout",
            "x-ISC_ServiceMethod":"logout",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      },
      "/openapi":{
         "get":{
            "operationId":"GenerateOpenAPI",
            "x-ISC_ServiceMethod":"GenerateOpenAPI",
            "responses":{
               "default":{
                  "description":"(Unexpected Error)"
               },
               "200":{
                  "description":"(Expected Result)"
               }
            }
         }
      }
   },
   "swagger":"2.0"
}

Enfoque Manual

El enfoque manual para generar un documento OpenAPI consiste en escribir el archivo de especificación manualmente en formato YAML o JSON. Este enfoque es especialmente útil cuando se desea tener un control total sobre el diseño de la API antes de su implementación, o cuando se documenta una API ya existente sin depender de herramientas automatizadas.

Para escribir el archivo de especificación OpenAPI, puedes consultar la documentación oficial de la versión 2.0 de la OpenAPI Specification, donde encontrarás información sobre los campos requeridos y cómo describir los endpoints, parámetros, respuestas y más. Esta guía detallada te ayudará a comprender cómo estructurar correctamente el archivo YAML o JSON para cumplir con los estándares de OpenAPI.

Un buen ejemplo de este enfoque es cuando se crea un servicio REST utilizando los métodos descritos en la documentación oficial de InterSystems IRIS. Puedes encontrar una introducción sobre cómo desarrollar y configurar una aplicación REST en IRIS en la siguiente página de la documentación, que describe paso a paso los métodos necesarios para exponer una aplicación RESTful con IRIS.

2 Comments
Discussão (2)2
Entre ou crie uma conta para continuar
Artigo
· Fev. 11 4min de leitura

%Status e Exceptions do IRIS

Você pode encontrar erros durante qualquer ponto da execução do programa, e existem várias maneiras de levantar e tratar essas exceções. Neste artigo, exploraremos como as exceções são tratadas de forma eficiente no IRIS.

Um dos tipos de retorno mais comumente usados é %Status, que é usado por métodos para indicar sucesso ou falha. Vamos começar discutindo os valores de %Status.

Trabalhando com %Status

O tipo de retorno %Status é usado para representar erros ou sucesso. Muitos métodos do sistema retornam %Status quando ocorre um erro. Você pode criar uma estrutura semelhante para os erros do seu aplicativo ou converter para %Status, mesmo quando você levantou exceções em seu código.

Vamos começar a criar os erros.

Macros

Quando falamos sobre erros, as Macros são essenciais e facilitam a criação de valores de Status no código. O IRIS fornece várias macros para criar e tratar erros dentro do código do seu aplicativo.

A macro mais comumente usada é $$$ERROR.

$$$ERROR

A macro $$$ERROR é especificamente projetada para gerar e retornar um valor %Library.%Status. É sua responsabilidade verificar o status antes de continuar a execução do seu programa. Esta macro está intimamente ligada a erros gerais do sistema. Tenha os seguintes pontos em mente ao usar esta macro:

-O primeiro argumento (códigos de erro) se refere aos códigos de erro gerais dentro do arquivo include %occErrors.
-Se você estiver usando erros predefinidos desse arquivo include, você pode usar a macro diretamente, com ou sem argumentos adicionais.

Observação: Antes de prosseguir, $SYSTEM.OBJ.DisplayError(status) ou $SYSTEM.Status.DisplayError(status)eram usados para exibir o(s) erro(s) e oferecem suporte à localização de strings. 

Set sc = $$$ERROR($$$NamespaceDoesNotExist,"TEST")
Do $SYSTEM.OBJ.DisplayError(sc)

output: ERROR #5015: Namespace 'TEST' does not exist1
Set sc = $$$ERROR($$$UserCTRLC)
Do $SYSTEM.OBJ.DisplayError(sc)

ouput: ERROR #834: Login aborted1

Se você usar qualquer outro código de erro que não esteja listado em %occErrors, um erro "Código de status desconhecido" será retornado. Sempre use o código de erro predefinido $$$GeneralError == 5001 para mensagens de erro gerais.

Exemplo de código de status desconhecido

Set sc = $$$ERROR(95875,"TEST Error")
Do $SYSTEM.Status.DisplayError(sc)

output: ERROR #95875: Unknown status code: 95875 (TEST Error)
Set sc = $$$ERROR($$$GeneralError,"TEST Error")
Do $SYSTEM.OBJ.DisplayError(sc)

output: ERROR #5001: TEST Error

$$$ADDSC

O %Status não contém necessariamente apenas um erro. Seu programa pode validar várias condições e manter o controle de todos os erros em um único status, e então usar a macro $$$ADDSC. Por exemplo, o método %ValidateObject() pode retornar múltiplos erros em uma única resposta, que usa essa funcionalidade.

A macro $$$ADDSC anexa um status a outro, e o método $SYSTEM.Status.AppendStatus executa a mesma função.

$$$ADDSC(sc1,sc2) / $SYSTEM.Status.AppendStatus(s1,s2) - anexa sc2 a sc1 e retorna um novo código de status.

ClassMethod AppendErrors()
{
    Set sc1 = $$$ERROR($$$UserCTRLC) 
    Set sc2 = $$$ERROR($$$NamespaceDoesNotExist,"TEST")
    Set sc = $$$ADDSC(sc1,sc2)
    Do $SYSTEM.Status.DisplayError(sc)
    Write !
    Set sc = $$$ADDSC(sc1,sc2)
    Do $SYSTEM.Status.DisplayError(sc)
}
output
LEARNING>do ##class(Learning.ErrorHandling).AppendErrors()
 
ERROR #834: Login aborted
ERROR #5015: Namespace 'TEST' does not exist
 
ERROR #834: Login aborted
ERROR #5015: Namespace 'TEST' does not exist

ambos os resultados são iguaias!

$$$GETERRORCODE

$$$GETERRORCODE(status) - Retorna o valor do código de erro do Status. Esta macro pertence ao arquivo %occStatus.inc

    Set status = $$$ERROR($$$UserCTRLC) 
    Write $$$GETERRORCODE(status),!
    #;output: 834
    Set status = $$$ERROR($$$GeneralError,"TEST Error")
    Write $$$GETERRORCODE(status)
    #;output: 5001

$$$GETERRORMESSAGE
$$$GETERRORMESSAGE(sc,num) - Esta macro retorna a parte do erro baseada no número (num) no %Status.
Aqui está um exemplo.

ClassMethod GetErrorMsgMacro()
{
	Set status = $$$ERROR($$$GeneralError,"TEST Error",1,$$$ERROR($$$GeneralError,"TEST Error2"))
	write $$$GETERRORMESSAGE(status),! ; It prints "TEST Error"
	#;
	Set st = $$$GETERRORMESSAGE(status,3) ; it get the "$$$ERROR($$$GeneralError,"TEST Error2")" in 3rd position based on the 2nd argument 
	write $$$GETERRORMESSAGE(st),! ; it prints TEST Error2
}

LEARNING>Do ##class(Learning.myexcept).GetErrorMsgMacro()
TEST Error
TEST Error2

 

Validar Status de Retorno

Agora que você criou o erro e o retornou para o seu programa, o próximo passo é validar se a resposta de retorno é bem-sucedida ou errônea.

A macro $$$ISERR verifica se o status representa um erro. Ela retorna 1 se o status indicar um erro, caso contrário, retorna 0. Existe outra macro, $$$ISOK, que retorna 1 quando o status é bem-sucedido.

Exibindo Erros

Se o seu programa apresentar erros inesperadamente (sempre espere o inesperado), você precisa exibir a mensagem de erro. A classe %SYSTEM.Status é especificamente projetada para visualizar ou criar valores %Status (se você preferir não usar macros) e já vimos os exemplos acima.

Aqui estão os métodos equivalentes em %SYSTEM.Status que substituem as macros:

Macro Methods
$$$ISERR $SYSTEM.Status.IsError()
$$$ISOK $SYSTEM.Status.IsOK()
$$$ADDSC $SYSTEM.Status.AppendStatus()
$$$ERROR $SYSTEM.Status.Error()
$$$OK $SYSTEM.Status.OK()
$$$GETERRORCODE $SYSTEM.Status.GetErrorCodes()

As exceções continuarão no próximo artigo.

Discussão (0)1
Entre ou crie uma conta para continuar