Nova postagem

Pesquisar

Resumo
· Fev. 3

Publications des développeurs d'InterSystems, semaine Janvier 27 - Février 02, 2025, Résumé

Janvier 27 - Février 02, 2025Week at a GlanceInterSystems Developer Community
Resumo
· Fev. 3
Artigo
· Fev. 3 3min de leitura

¿Faltan SQL variables de host ?

Variables de host son una característica de programación bastante común en muchas implementaciones de SQL.
Una pregunta reciente en DC me hizo darme cuenta de que en IRIS, Caché, Ensemble,... 
las variables del host simplemente existen dentro del embedded SQL.

>  You can supply host variables for Embedded SQL queries only. <
Se incluyen ejemplos relacionados en la documentación disponible.

A continuación se incluye una descripción de una solución alternativa si no utiliza o no puede utilizar embedded SQL.
La idea básica es utilizar PPG (Process Private Globals) para almacenar la imitación de una variable del host.

Una de las principales razones para utilizar PPG es el hecho de que se eliminan automáticamente al final del proceso.
Otra idea es evitar conflictos con las matrices de variables locales y el alcance de las variables locales versus globales.
Además, no es necesario realizar ninguna actividad de limpieza.

De hecho, es un conjunto de 3 métodos SQL.

  • HDEC para imitar SQL DECLARE @var y SQL SET @-var
  • HGETV y HGETI  para devolver el valor de la variable como VARCHAR o INTT
    • Como característica adicional, se devuelve NULL si la variable no se configuró o declaró antes
    • si es necesario devolver cualquier otro tipo de datos es bastante fácil
  • HDEL se proporciona si surge la improbable necesidad de eliminar una variable del lenguaje principal
Class User.HostVar
{
ClassMethod GetV(name) As %String [ SqlName = HGETV, SqlProc ]
{
    quit $get(^||host($g(name,"%")))
}
ClassMethod GetI(name) As %Integer [ SqlName = HGETI, SqlProc ]
{
    quit $get(^||host($g(name,"%")))
}
ClassMethod Declare(name, val) As %Integer [ SqlName = HDEC, SqlProc ]
{
    set ^||host($g(name,"%"))=$g(val)
    quit $$$OK
}
ClassMethod Del(name) As %Integer [ SqlName = HDEL, SqlProc ]
{
    kill ^||host($g(name,"%"))
    quit $$$OK
}
}

Mi ejemplo contiene 2 variantes para la implementación.
El primero es ObjectScript directo,
esta variante también está disponible en IPM. 

El segundo está basado en SQL y se puede implementar también a través de ODBC/JDBC.

CREATE or REPLACE
PROCEDURE HDEC(IN name VARCHAR(50), IN val VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  { 	set ^||host($g(name,"%"))=$g(val)
	quit $$$OK
  } 
CREATE or REPLACE PROCEDURE
HGETV(IN name VARCHAR(50)) RETURNS VARCHAR(50)
  LANGUAGE OBJECTSCRIPT 
  {
 	quit $get(^||host($g(name,"%")))
  }
CREATE or REPLACE PROCEDURE
HGETI(IN name VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  {
 	quit $get(^||host($g(name,"%")))
  }  
CREATE or REPLACE  
PROCEDURE HDEL(IN name VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  { 	kill ^||host($g(name,"%"))
	quit $$$OK
  } 

Ambas variantes están diseñadas para poder utilizarse sin un prefijo de paquete.
Por lo tanto, se utilizó el paquete Usuario (el predeterminado) que se asigna
al esquema predeterminado SQLUser en SQL.

Durante las pruebas detecté que forzar una secuencia de Configuración y Consumo
Estas variables del host pueden ser un ejercicio complicado si desea ejecutarlas
internamente.una única declaración SQL.
Logré proporcionar una secuencia predecible solo usando una construcción CASE.

SELECT 
CASE
  WHEN HDEC('rcc',66) > 0  -- set host var 
   THEN HGETI('rcc')-5||' ** '||HGETV('rcc')
END  

Dentro de un Stored Procedure no enfrenta este problema.

Se crearon mi ejemplo y también el paquete proporcionado en Open Exchange.
y probado en IRIS. Aunque la construcción es bastante básica y también se
ejecuta sin ningún cambio en Caché, Ensemble, ... y sus derivados y
por supuesto en todos los derivados HEALTH* de IRIS.

Mi única duda es sobre una base de datos sharded en combinación con
Process Private Globals. Simplemente no tenía ninguna configuración disponible para probar este escenario. 

No doy por sentado que esta propuesta sea la solución definitiva.
Situaciones específicas pueden requerir un enfoque más sofisticado
o bien construcciones más simples.

Como mencioné anteriormente veo la gran ventaja de tener una solución.
que se puede utilizar a través de un acceso ODBC o JDBC y no
requieren codificación con VSCode o Studio.

GitHub
Vídeo en inglés

Implementation of Ideas Portal   

 
Esperando sus votos en el concurso.

 

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

SQL Host Variables missing ?

Host Variables are a rather common programming feature in many implementations of SQL. 
A recent question in DC made me aware that in IRIS, Caché, Ensemble, ... 
host variables just exist within embedded SQL

>  You can supply host variables for Embedded SQL queries only. <

Related examples are included in the available Documentation

This is a description  for a workaround if you don't / can't use embedded SQL.
The basic idea is to use PPG (Process Private Globals)  to store the mimic of a host variable.
A major reason to use PPG is the fact that they get deleted automatically at the end of process.
Another idea is to avoid conflicts with local variable arrays and local versus global variable scope
In addition there is no need for an clean up activity.

In fact it is a set of 3 SQL Methods:

  • HDEC to mimic SQL DECLARE @var and SQL SET @var 
  • HGETV and HGETI  to return the variable value as VARCHAR or INT
    • As a side feature NULL is returned if the variable wasn't set of declared before
    • if required returning any other data type is rather easy
  • HDEL is provided if there raises the unlikely need to delete a host variable
Class User.HostVar
{
ClassMethod GetV(name) As %String [ SqlName = HGETV, SqlProc ]
{
    quit $get(^||host($g(name,"%")))
}
ClassMethod GetI(name) As %Integer [ SqlName = HGETI, SqlProc ]
{
    quit $get(^||host($g(name,"%")))
}
ClassMethod Declare(name, val) As %Integer [ SqlName = HDEC, SqlProc ]
{
    set ^||host($g(name,"%"))=$g(val)
    quit $$$OK
}
ClassMethod Del(name) As %Integer [ SqlName = HDEL, SqlProc ]
{
    kill ^||host($g(name,"%"))
    quit $$$OK
}
}

My example contains 2 variants for implementation
The first is straight ObjectScript,
this variant is also available in IPM. 

The second is SQL based and can be implemented also over ODBC / JDBC 

CREATE or REPLACE
PROCEDURE HDEC(IN name VARCHAR(50), IN val VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  { 	set ^||host($g(name,"%"))=$g(val)
	quit $$$OK
  } 
CREATE or REPLACE PROCEDURE
HGETV(IN name VARCHAR(50)) RETURNS VARCHAR(50)
  LANGUAGE OBJECTSCRIPT 
  {
 	quit $get(^||host($g(name,"%")))
  }
CREATE or REPLACE PROCEDURE
HGETI(IN name VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  {
 	quit $get(^||host($g(name,"%")))
  }  
CREATE or REPLACE  
PROCEDURE HDEL(IN name VARCHAR(50)) RETURNS INT
  LANGUAGE OBJECTSCRIPT 
  { 	kill ^||host($g(name,"%"))
	quit $$$OK
  } 

Both variants are designed to be usable without a package prefix.
Therefore used package User (the default) mapping to default schema SQLUser in SQL.

During testing I detected that forcing a sequence of Setting and Consuming
this host variables can be a tricky exercise if you want to execute it inside
a single SQL statement.
I managed to provide a predictable sequence only using a CASE construct.

SELECT 
CASE
  WHEN HDEC('rcc',66) > 0  -- set host var 
   THEN HGETI('rcc')-5||' ** '||HGETV('rcc')
END  

Within a stored procedure you don't face this problem.

My example and also the provided package in Open Exchange were built
and tested on IRIS. Though the construct is rather basic and also runs
without any change on Caché, Ensemble, ... and it's derivates and
of course on all HEALTH* derivates of IRIS.

My only doubt is about a sharded database in combination with 
Process Private Globals. I had just no setup available for testing  this scenario. 

I don't assume that this proposal is the ultimate solution.
Specific situations may require a more sophisticated approach
or otherwise more simple constructions.

As mentioned earlier I see the big advantage to have a solution
that can be used over ans ODBC or JDBC access and doesn't
require coding with VSCode or Studio.

Video

GitHub

Implementation of Ideas Portal

 

Hoping for your votes.in contest.

Discussão (0)1
Entre ou crie uma conta para continuar
Pergunta
· Fev. 3

Load ObjectScript external file and run code

Hi,

I have Objectscript routine stored in an external Linux file which I've called /my/home/DisplayDB.int

This file does not include any Class definitions and is simply a set a Object script routines. I think this is called INT objectscript

The file looks like this:

set db=##class(Config.Databases).DatabasesByServer("",.dbList)
for i=1:1:$LENGTH(dbList,",") {
  set dbName= $PIECE(dbList,",",i)
  write dbName,!
}

How do I load and compile the Objectscript code?
Do $system.OBJ.Load("/my/home/DisplayDB.int", "ck")

How would I run the code?
do ^DisplayDB

Thanks in advance for any help

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