#Terminal

0 Seguidores · 31 Publicaciones

Publicaciones relacionadas con las discusiones sobre el uso de la herramienta Terminal.

Artículo Katherine Duran · mayo 27, 2025 7m read

InterSystems IRIS permite ejecutar consultas SQL directamente desde ObjectScript mediante:

  • SQL Embebido (Embedded SQL): consultas SQL compiladas en tiempo de desarrollo, con chequeo de tipos y mayor eficiencia.
  • SQL Dinámico (Dynamic SQL): permite construir y ejecutar sentencias SQL en tiempo de ejecución, ideal para casos flexibles o condicionales.

Que es SQL (Structured Query Language) es un lenguaje estándar utilizado para interactuar con bases de datos relacionales. Permite realizar operaciones como:

3
7 180
Artículo Pierre-Yves Duquesnoy · mar 26, 2025 5m read

Las versiones recientes de IRIS contienen varios cambios que afectan a la instalación y condiguración de la herramienta OpenSource WebTerminal.

En este articulo, vamos a ver los pasos de instalación, y aprender a buscar y resolver los errores del WebGateway paso a paso.
Esta guía de instalación se ha realizado con la versiones siguientes, las más recientes soportadas a fecha de marzo de 2025:

  • Windows 2022 on Internet Information Server (IIS)
  • IRIS 2024.3 
  • Package Manager 0.9.2
  • WebTerminal 4.9.6
0
0 70
Artículo Luis Angel Pérez Ramos · mar 13, 2025 1m read

¡Hola compañeros!

Otra vez más me he dado cuenta de que no hay una forma supersencilla de mostrar el error de la variable %Status, cosa que necesito con relativa frecuencia desde el terminal.

Sí, conozco las macros $$$, pero no son demasiado útiles en un terminal.

Habitualmente lo que hago es intentar recordar de memoria o copiar de algún sitio la fórmula:

USUARIO>w $System.State.DisplayError(st)
0
0 45
Artículo Dmitry Maslennikov · oct 1, 2024 2m read

Hemos tenido Webterminal disponible durante bastante tiempo, pero era limitado, no todas las funciones funcionaban allí. No había soporte para shell ni para la última funcionalidad de soporte integrado de Python. Hay algunos problemas con las herramientas que requieren el modo de programador. La autenticación básica no es tan práctica como una simple página de inicio de sesión, donde podríais tener opciones para agregar vuestra propia página de login, en caso de que deseaseis cambiar la forma de iniciar sesión en la aplicación, como por ejemplo usando SSO (inicio de sesión único).

Con el terminal Iris original, envuelto en un formulario web y utilizando xterm.js, una de las herramientas más usadas en el mundo web, como en VSCode, junto con algo de magia de Python, que ayudó con la comunicación interprocesos tty, podemos llevar el terminal a la web con todas sus capacidades.

iTerm

0
0 98
Pregunta Enric Moya Sánchez · jun 14, 2024
Buenos dias
Cuando ejecuto algun comando en el webterminal que tiene mucha salida (por ejemplo zw ^IRIS.Msg), el comando se ejecuta bien pero el webterminal se queda en negro durante mucho rato (15 minutos) hasta que me da la salida.
Supongo que es algo de que le cuesta dar todo el texto a traves de la web, ya que el comando en sí tarda muy poco en ejecutarse.

¿Alguien más con este problema, alguna solucion?

Gracias

4
0 238
Artículo Alberto Fuentes · ene 11, 2024 2m read

¿Alguna vez habéis estado editando ficheros en VS Code, pero necesitábais comprobar el valor de un global o ejecutar algunos comandos de ObjectScript? Ahora podéis hacerlo, sin necesidad de configuración! Si tenéis la versión 2.10.0 o posterior de la extensiónvscode-objectscript y estáis conectados a InterSystems IRIS 2023.2 o posterior, ahora podéis abrir una conexión del terminal a vuestro servidor, sin importar dónde se encuentre.

Hay tres formas de abrir este nuevo terminal:

1
0 262
Artículo Kurro Lopez · feb 9, 2024 2m read

Interactuar con usuarios en la terminal: una guía para usar %Library.Prompt en IRIS

 

¿Alguna vez te has preguntado cómo comandos como ^DATABASE atraen a los usuarios en la terminal? O tal vez esté escribiendo una rutina de automatización y desee formas de especificar opciones directamente desde la terminal. Afortunadamente, la clase %Library.Prompt en IRIS ofrece una forma sencilla de hacerlo.

Entradas de texto

Para entradas básicas, como pedirle al usuario que proporcione una ruta de archivo o un espacio de nombres, utilice el siguiente código:

0
0 164
Artículo Elijah Tamarchenko · feb 6, 2024 2m read

¡Hola Comunidad!

Hace poco me impresionó el artículo de @Dan Pasco donde comparte cómo usa los alias de terminal.

Los alias de terminal son una herramienta muy poderosa para desarrolladores y administradores de sistemas, si con frecuencia necesitan llamar a algunas expresiones de terminal engorrosas y hacerlas más cortas y limpias. Aquí está la documentación.

Pero ¿qué pasa con los entornos Docker? ¿Qué sucede si sois fanáticos de los entornos de desarrollo de Docker, pero también queréis seguir usando vuestros alias favoritos con Docker?

Resulta que es muy posible.

0
0 180
Artículo Alberto Fuentes · ene 31, 2024 13m read

Tenemos un conjunto de datos bastante apetecible con recetas escritas por múltiples usuarios de Reddit, sin embargo, la mayor parte de la información está en texto libre en forma de título y descripción de un mensaje. Vamos a averiguar cómo podemos, de forma muy sencilla, cargar los datos, extraer algunas características y analizarlos empleando funcionalidades de LLM (Large Language Model) de OpenAI desde Python Embebido y el framework Langchain.

Cargar los datos

Lo primero es lo primero: ¿necesitamos cargar los datos o podemos sencillamente conectarnos a ellos?

Hay diferentes formas para plantearlo: por ejemplo, con el Mapeo de registros CSV que puedes utilizar en una producción de interoperabilidad o incluso instalar directamente una aplicación de OpenExchange como csvgen para que nos ayude.

Utilizaremos en este caso las Foreign Tables. Una funcionalidad muy útil para proyectar datos físicamente almacenados en otra parte y tenerlos accesibles desde el SQL de IRIS. Podemos utilizarlo directamente para echar un primer vistazo a los ficheros del conjunto de datos.

Creamos un Foreign Server:

CREATE FOREIGN SERVER dataset FOREIGN DATA WRAPPER CSV HOST '/app/data/'

Y a continuación, creamos una Foreign Table que se conecta al fichero CSV:

CREATE FOREIGN TABLE dataset.Recipes (
  CREATEDDATE DATE,
  NUMCOMMENTS INTEGER,
  TITLE VARCHAR,
  USERNAME VARCHAR,
  COMMENT VARCHAR,
  NUMCHAR INTEGER
) SERVER dataset FILE 'Recipes.csv' USING
{
  "from": {
    "file": {
       "skip": 1
    }
  }
}

¡Y ya está!, inmediatamente podemos lanzar consultas SQL sobre dataset.Recipes: image

## ¿Qué datos necesitamos? Los datos son muy interesantes y tenemos hambre. Sin embargo, si queremos decidir qué receta vamos a cocinar necesitamos algo más de información que podamos utilizar para analizar las recetas.

Vamos a trabajar con dos clases persistentes (tablas):

  • yummy.data.Recipe: una clase que contiene el título y la descripción de la receta así como algunas otras propiedades que queremos extraer y analizar (por ejemplo: Score, Difficulty, Ingredients, CuisineType, PreparationTime).
  • yummy.data.RecipeHistory: una clase sencilla para anotar un registro de qué estamos haciendo con la receta.

Podemos ahora cargar en nuestras tablas yummy.data* el contenido del conjunto de datos de recetas:

do ##class(yummy.Utils).LoadDataset()

Hasta aquí tiene buena pinta, pero aún debemos averiguar cómo vamos a generar los datos para los campos como: Score, Difficulty, Ingredients, PreparationTime and CuisineType.

## Analizar las recetas Queremos procesar el título y la descripción de cada receta y:

  • Extraer información como Difficulty, Ingredients, CuisineType, etc.
  • Construir nuestra propia puntuación de la receta basada en nuestro criterio, de forma que podamos decidir qué vamos a cocinar.

Vamos a utilizar lo siguiente:

  • yummy.analysis.Analysis - una estructura genérica de análisis que vamos a re-utilizar en caso de que queramos implementar diferentes tipos de análisis.
  • yummy.analysis.SimpleOpenAI - un análisis que usa Python Embebido + framework Langchain + OpenAI LLM.

Los LLM (Large Language Models) son una herramienta realmente increíble para procesar lenguaje natural.

LangChain está preparado para trabajar con Python, así que podemos utilizarlo directamente en InterSystems IRIS a través de Embedded Python.

La clase SimpleOpenAI tiene esta pinta:

/// Simple OpenAI analysis for recipes
Class yummy.analysis.SimpleOpenAI Extends Analysis
{

Property CuisineType As %String;

Property PreparationTime As %Integer;

Property Difficulty As %String;

Property Ingredients As %String;

/// Run
/// You can try this from a terminal:
/// set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8))
/// do a.Run()
/// zwrite a
Method Run()
{
    try {
        do ..RunPythonAnalysis()

        set reasons = ""

        // mis estilos de cocina favoritos
        if "spanish,french,portuguese,italian,korean,japanese"[..CuisineType {
            set ..Score = ..Score + 2
            set reasons = reasons_$lb("It seems to be a "_..CuisineType_" recipe!")
        }

        // no quiero estar el día entero cocinando :)
        if (+..PreparationTime < 120) {
            set ..Score = ..Score + 1
            set reasons = reasons_$lb("You don't need too much time to prepare it") 
        }
        
        // bonus para mis ingredientes favoritos!
        set favIngredients = $listbuild("kimchi", "truffle", "squid")
        for i=1:1:$listlength(favIngredients) {
            set favIngred = $listget(favIngredients, i)
            if ..Ingredients[favIngred {
                set ..Score = ..Score + 1
                set reasons = reasons_$lb("Favourite ingredient found: "_favIngred)
            }
        }

        set ..Reason = $listtostring(reasons, ". ")

    } catch ex {
        throw ex
    }
}

/// Update recipe with analysis results
Method UpdateRecipe()
{
    try {
        // call parent class implementation first
        do ##super()

        // add specific OpenAI analysis results
        set ..Recipe.Ingredients = ..Ingredients
        set ..Recipe.PreparationTime = ..PreparationTime
        set ..Recipe.Difficulty = ..Difficulty
        set ..Recipe.CuisineType = ..CuisineType

    } catch ex {
        throw ex
    }
}

/// Run analysis using embedded Python + Langchain
/// do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8)).RunPythonAnalysis(1)
Method RunPythonAnalysis(debug As %Boolean = 0) [ Language = python ]
{
    # load OpenAI APIKEY from env
    import os
    from dotenv import load_dotenv, find_dotenv
    _ = load_dotenv('/app/.env')

    # account for deprecation of LLM model
    import datetime
    current_date = datetime.datetime.now().date()
    # date after which the model should be set to "gpt-3.5-turbo"
    target_date = datetime.date(2024, 6, 12)
    # set the model depending on the current date
    if current_date > target_date:
        llm_model = "gpt-3.5-turbo"
    else:
        llm_model = "gpt-3.5-turbo-0301"

    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import ChatPromptTemplate
    from langchain.chains import LLMChain

    from langchain.output_parsers import ResponseSchema
    from langchain.output_parsers import StructuredOutputParser

    # init llm model
    llm = ChatOpenAI(temperature=0.0, model=llm_model)

    # prepare the responses we need
    cuisine_type_schema = ResponseSchema(
        name="cuisine_type",
        description="What is the cuisine type for the recipe? \
                     Answer in 1 word max in lowercase"
    )
    preparation_time_schema = ResponseSchema(
        name="preparation_time",
        description="How much time in minutes do I need to prepare the recipe?\
                     Anwer with an integer number, or null if unknown",
        type="integer",
    )
    difficulty_schema = ResponseSchema(
        name="difficulty",
        description="How difficult is this recipe?\
                     Answer with one of these values: easy, normal, hard, very-hard"
    )
    ingredients_schema = ResponseSchema(
        name="ingredients",
        description="Give me a comma separated list of ingredients in lowercase or empty if unknown"
    )
    response_schemas = [cuisine_type_schema, preparation_time_schema, difficulty_schema, ingredients_schema]

    # get format instructions from responses
    output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
    format_instructions = output_parser.get_format_instructions()
    
    analysis_template = """\
    Interprete and evaluate a recipe which title is: {title}
    and the description is: {description}
    
    {format_instructions}
    """
    prompt = ChatPromptTemplate.from_template(template=analysis_template)

    messages = prompt.format_messages(title=self.Recipe.Title, description=self.Recipe.Description, format_instructions=format_instructions)
    response = llm(messages)

    if debug:
        print("======ACTUAL PROMPT")
        print(messages[0].content)
        print("======RESPONSE")
        print(response.content)

    # populate analysis with results
    output_dict = output_parser.parse(response.content)
    self.CuisineType = output_dict['cuisine_type']
    self.Difficulty = output_dict['difficulty']
    self.Ingredients = output_dict['ingredients']
    if type(output_dict['preparation_time']) == int:
        self.PreparationTime = output_dict['preparation_time']

    return 1
}

}

El método RunPythonAnalysis es donde sucede todo lo relativo a OpenAI :). Puedes probarlo directamente desde tu terminal utilizando una receta en particular:

do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)

Obtendremos un resultado como el siguiente:

USER>do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)
======ACTUAL PROMPT
                    Interprete and evaluate a recipe which title is: Folded Sushi - Alaska Roll
                    and the description is: Craving for some sushi but don't have a sushi roller? Try this easy version instead. It's super easy yet equally delicious!
[Video Recipe](https://www.youtube.com/watch?v=1LJPS1lOHSM)
# Ingredients
Serving Size:  \~5 sandwiches      
* 1 cup of sushi rice
* 3/4 cups + 2 1/2 tbsp of water
* A small piece of konbu (kelp)
* 2 tbsp of rice vinegar
* 1 tbsp of sugar
* 1 tsp of salt
* 2 avocado
* 6 imitation crab sticks
* 2 tbsp of Japanese mayo
* 1/2 lb of salmon  
# Recipe     
* Place 1 cup of sushi rice into a mixing bowl and wash the rice at least 2 times or until the water becomes clear. Then transfer the rice into the rice cooker and add a small piece of kelp along with 3/4 cups plus 2 1/2 tbsp of water. Cook according to your rice cookers instruction.
* Combine 2 tbsp rice vinegar, 1 tbsp sugar, and 1 tsp salt in a medium bowl. Mix until everything is well combined.
* After the rice is cooked, remove the kelp and immediately scoop all the rice into the medium bowl with the vinegar and mix it well using the rice spatula. Make sure to use the cut motion to mix the rice to avoid mashing them. After thats done, cover it with a kitchen towel and let it cool down to room temperature.
* Cut the top of 1 avocado, then slice into the center of the avocado and rotate it along your knife. Then take each half of the avocado and twist. Afterward, take the side with the pit and carefully chop into the pit and twist to remove it. Then, using your hand, remove the peel. Repeat these steps with the other avocado. Dont forget to clean up your work station to give yourself more space. Then, place each half of the avocado facing down and thinly slice them. Once theyre sliced, slowly spread them out. Once thats done, set it aside.
* Remove the wrapper from each crab stick. Then, using your hand, peel the crab sticks vertically to get strings of crab sticks. Once all the crab sticks are peeled, rotate them sideways and chop them into small pieces, then place them in a bowl along with 2 tbsp of Japanese mayo and mix until everything is well mixed.
* Place a sharp knife at an angle and thinly slice against the grain. The thickness of the cut depends on your preference. Just make sure that all the pieces are similar in thickness.
* Grab a piece of seaweed wrap. Using a kitchen scissor, start cutting at the halfway point of seaweed wrap and cut until youre a little bit past the center of the piece. Rotate the piece vertically and start building. Dip your hand in some water to help with the sushi rice. Take a handful of sushi rice and spread it around the upper left hand quadrant of the seaweed wrap. Then carefully place a couple slices of salmon on the top right quadrant. Then place a couple slices of avocado on the bottom right quadrant. And finish it off with a couple of tsp of crab salad on the bottom left quadrant. Then, fold the top right quadrant into the bottom right quadrant, then continue by folding it into the bottom left quadrant. Well finish off the folding by folding the top left quadrant onto the rest of the sandwich. Afterward, place a piece of plastic wrap on top, cut it half, add a couple pieces of ginger and wasabi, and there you have it.
                    
                    The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":
json
{
        "cuisine_type": string  // What is the cuisine type for the recipe?                                  Answer in 1 word max in lowercase
        "preparation_time": integer  // How much time in minutes do I need to prepare the recipe?                                    Anwer with an integer number, or null if unknown
        "difficulty": string  // How difficult is this recipe?                               Answer with one of these values: easy, normal, hard, very-hard
        "ingredients": string  // Give me a comma separated list of ingredients in lowercase or empty if unknown
}

                    
======RESPONSE
json
{
        "cuisine_type": "japanese",
        "preparation_time": 30,
        "difficulty": "easy",
        "ingredients": "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
}

Tiene muy buena pinta. Parece que nuestro prompt o pregunta a OpenAI es capaz de devolvernos información que realmente podemos utilizar. Vamos a ejecutar el análisis completo desde el terminal:

set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12))
do a.Run()
zwrite a
USER>zwrite a
a=37@yummy.analysis.SimpleOpenAI  ; <OREF>
+----------------- general information ---------------
|      oref value: 37
|      class name: yummy.analysis.SimpleOpenAI
| reference count: 2
+----------------- attribute values ------------------
|        CuisineType = "japanese"
|         Difficulty = "easy"
|        Ingredients = "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
|    PreparationTime = 30
|             Reason = "It seems to be a japanese recipe!. You don't need too much time to prepare it"
|              Score = 3
+----------------- swizzled references ---------------
|           i%Recipe = ""
|           r%Recipe = "30@yummy.data.Recipe"
+-----------------------------------------------------

## Analizar todas las recetas Naturalmente, querremos ejecutar el análisis para todas las recetas que hemos cargado.

Puedes analizar un rango de recetas (utilizando sus identificadores), de esta forma:

USER>do ##class(yummy.Utils).AnalyzeRange(1,10)
> Recipe 1 (1.755185s)
> Recipe 2 (2.559526s)
> Recipe 3 (1.556895s)
> Recipe 4 (1.720246s)
> Recipe 5 (1.689123s)
> Recipe 6 (2.404745s)
> Recipe 7 (1.538208s)
> Recipe 8 (1.33001s)
> Recipe 9 (1.49972s)
> Recipe 10 (1.425612s)

Después de eso, vamos a echar un vistazo de nuevo a la tabla de recetas y comprobemos los resultados:

select * from yummy_data.Recipe

image

Creo que podría intentar la Pizza con calabaza o el Tofu con Kimchi y cerdo al estilo coreano :). De todas formas, debo asegurarme y preguntar en casa antes de empezar a cocinar :)

Conclusión

Puedes encontrar el ejemplo completo en https://github.com/isc-afuentes/recipe-inspector

Con este ejemplo sencillo hemos aprendido cómo utilizar técnicas LLM para extraer características y analizar ciertas partes de nuestros datos en InterSystems IRIS.

Con esto como punto de partida, podrías plantearte cosas como:

  • Utilizar InterSystems BI para explorar y navegar tus datos utilizando cubos y cuadros de mando.
  • Crear una aplicación web y añadir una interfaz gráfica (e.g. con Angular) para esta aplicación, podrías utilizar paquetes como RESTForms2 para generar automáticamente APIs REST para tus clases persistentes.
  • ¿Qué tal si almacenas si una receta te gusta o no, y después intentas determinar si una nueva receta te gustará? Podrías plantearlo con IntegratedML, o incluso con LLM pasándole algunos datos de ejemplo e implementando un caso de uso tipo RAG (Retrieval Augmented Generation).

¿Qué otras cosas se os ocurren?

0
0 190
Artículo Alberto Fuentes · ene 25, 2024 1m read

Creo que ésta es una forma bastante interesante de instalar un terminal web en un entorno en el que puedes acceder al Portal de Gestión/Visual Studio Code, pero no al terminal.

En este caso, zpm ya estaba presente. En caso contrario, se puede instalar también en la misma clase.

  1. Crear una clase que instalará webterminal utilizando zpm.
  2. Compilar. Esto llevará un rato (ya que hará la descarga y la instalación), y después se verá el resultado desde zpm!
  3. Ahora se puede abrir el terminal web accediendo a http://your-host/terminal/
Class Theo.Util.Webterminal Extends %RegisteredObject
{

/// Description
ClassMethod install() As %Status [ CodeMode = objectgenerator ]
{
    zpm "install webterminal"
}

}
0
0 131
Artículo Luis Angel Pérez Ramos · nov 22, 2023 3m read

Introducción

A InterSystems le gustaría optimizar IRIS para aprovechar las modernas extensiones del conjunto de instrucciones de la CPU.  Eso está genial para el rendimiento del producto, pero ¿cómo sabéis si vuestra CPU seguirá siendo compatible con las nuevas versiones de IRIS? En este artículo os explico cómo saber la familia de microarquitectura de la CPU, y cómo averiguar las extensiones específicas del conjunto de instrucciones de la CPU.

0
0 90
Artículo Alberto Fuentes · mayo 5, 2023 3m read

¡Hola desarrolladores!

Hay una actualización reciente para las imágenes de la comunidad de desarrolladores de InterSystems IRIS e InterSystems IRIS For Health.

Esta versión incluye soporte para variables de entorno.

Actualmente se soportan 3 variables de entorno:

  • IRIS_USERNAME=usuario a crear
  • IRIS_PASSWORD=password del usuario
  • IRIS_NAMESPACE=crear namespace si no existe

Esto es lo que puedes hacer:

Arrancar iris con un usuario y password:

docker run --rm --name iris-sql -d -p 9091:1972 -p 9092:52773  -e IRIS_PASSWORD=demo -e IRIS_USERNAME=demo intersystemsdc/iris-community
0
0 149
Artículo Nancy Martínez · oct 18, 2022 1m read

¡Hola desarrolladores!

Para mí, una de las peores cosas de ObjectScript es tener que escribir la sentencia ##class(Class).Method() para llamar a un método de clase en código o en un terminal. Incluso envié una idea para simplificarlo en ObjectScript.

¡Pero! Hay una nueva funcionalidad en VSCode ObjectScript que acaba de ser añadida al plugin - ¡Copy Invocation!

Solo hay que poner el cursor sobre el enlace Copy Invocation que aparece encima de cada método de clase del código, hacer clic en él y la invocación se copia en el buffer:

Pegadlo donde queráis que se ejecute.

0
0 161
Pregunta Kurro Lopez · jul 21, 2022

Hola a todos,

Acabo de actualizar la versión de WebTerminal usando el link, pero ahora no funciona.

Cuando llamas a /terminal está mostrando el siguiente error:

{
    "errors":[ {
            "code":5002,
            "domain":"%ObjectErrors",
            "error":"ERROR #5002: Error de cache: <INVALID OREF>zWrite+5^WebTerminal.StaticContent.1",
            "id":"ObjectScriptError",
            "params":["<INVALID OREF>zWrite+5^WebTerminal.StaticContent.1"
            ]
        }
    ],
    "summary":"ERROR #5002: Error de cache: <INVALID OREF>zWrite+5^WebTerminal.StaticContent.1"
}
2
0 165
Artículo Joel Solon · ene 7, 2022 1m read

¡Hola a todos!

¿Cuándo una publicación en la Comunidad de Desarrolladores no es una publicación en la Comunidad de Desarrolladores? ¡Cuando es solo un grupo de frases envolviendo un enlace a la Documentación de InterSystems! Y qué mejor manera de empezar 2022 que mostrándoos algo muy chulo que ha estado disponible desde la versión 2020.3??:

Cómo repetir comandos anteriores

¡Creo que os encantará! Y contadme vuestro alias favorito en los comentarios. ¡Feliz año nuevo!

0
0 164
Pregunta Peter N · jul 11, 2020

Intento ejecutar una pequeña rutina de prueba (adivinar un número aleatorio) en WebTerminal pero el resultado parece roto.
IRISterminal:

 WebTerminal:

Creo que se relaciona con el  backspace.
¿Se requiere algún ajuste especial?

El código:

a
 q=".......... guess [0..9]: " 
 i=1:1 if ! $c(9),"thank you",! q
 q  
b
 !,i,$c(9),q
 f  v#1 q:(v?.1n) " !no number",$c(8,8,8,8,8,8,8,8,8,8,8,8)
 " "
 r=$R(10),p=$s(v="":1,v=r:"!",v>r:"<",1:">")
 x=q,$e(x,r+1)="*",$e(x,v+1)=$s(v=r:"!",v>r:"<",1:">") 
 q:p  $c(13),$c(9),p=v=q

2
0 152
Artículo Mathew Lambert · jul 7, 2020 6m read

Introducción

Si gestionas múltiples instancias de Caché en varios servidores, puede que quieras ejecutar código arbitrario de una instancia de Caché en otra. Los administradores de sistemas y especialistas de soporte técnico también podrían querer ejecutar un código arbitrario en servidores Caché remotos. Para satisfacer estas necesidades, he desarrollado una herramienta especial llamadaRCE.
En este artículo, analizaremos cuáles son las formas más comunes de resolver tareas similares y cómo RCE (Remote Code Execution) puede ser útil.
0
0 439
Artículo Kurro Lopez · mayo 17, 2020 7m read

En este artículo me gustaría contarle acerca de las macros en InterSystems Caché. Una macro es un nombre simbólico que se reemplaza con un conjunto de instrucciones durante la compilación. Una macro puede "desplegarse" en varios conjuntos de instrucciones cada vez que se llama, dependiendo de los parámetros que se le pasen y los escenarios activados. Esto puede ser tanto código estático como el resultado de la ejecución de ObjectScript. Echemos un vistazo a cómo puede usarlos en su aplicación.

Compilación

Para empezar, veamos cómo se compila el código ObjectScript:

  1. El compilador de clases usa definiciones de clase para generar código MAC
  2. En algunos casos, el compilador usa clases como base para generar clases adicionales. Puede ver estas clases en el estudio, pero no debe cambiarlas. Esto sucede, por ejemplo, al generar clases que definen servicios web y clientes
  3. El compilador de clases también genera un descriptor de clase utilizado por Caché en tiempo de ejecución
  4. El preprocesador (también conocido como macro preprocesador, MPP) utiliza archivos INC y reemplaza las macros. Además, también procesa SQL incorporado en rutinas ObjectScript
  5. Todos estos cambios tienen lugar en la memoria; el código del usuario permanece sin cambios
  6. Después de eso, el compilador crea código INT para las rutinas de ObjectScript. Esta capa se conoce como código intermedio. Todo el acceso a los datos en este nivel se proporciona a través de globals
  7. El código INT es compacto y puede ser leído por un humano. Para verlo en el Studio, presione Ctrl + Shift + V.
  8. El código INT se usa para generar código OBJ
  9. El código OBJ es utilizado por la máquina virtual Caché. Una vez que se genera, el código CLS / MAC / INT ya no es necesario y puede eliminarse (por ejemplo, si queremos enviar un producto sin el código fuente)
  10. Si la clase es persistent, el compilador SQL creará las tablas SQL correspondientes

Macros

Como mencioné antes, una macro es un nombre simbólico que se reemplaza por el preprocesador con un conjunto de instrucciones. Una macro se define con la ayuda del comando #Define seguido del nombre de la macro (quizás con una lista de argumentos) y su valor:

#Define Macro[(Args)] [Value]

¿Dónde se pueden definir las macros? Ya sea en el código o en forma independiente en archivos INC que contiene solo macros. Los archivos necesarios se incluyen en las clases al comienzo de las definiciones de clase utilizando el comando Include MacroFileName - este es el método principal y preferido para incluir macros en clases. Las macros incluidas de esta manera se pueden usar en cualquier parte de una clase. Puedes usar el comando #Include MacroFileName para incluir un archivo INC con macros en rutinas MAC o el código de métodos de clase particulares.

Tenga en cuenta que los generadores de métodos requieren #Include dentro de su propio cuerpo si quieres usar macros en tiempo de compilación o uso de la palabra clave IncludeGenerator en una clase.

Para hacer que la macro esté disponible en el autocompletado de estudio, agregue /// en una línea anterior:

///
#Define Macro[(Args)] [Value]

Ejemplos

Ejemplo 1

Pasemos ahora a algunos ejemplos, y ¿por qué no comenzamos con el mensaje estándar "Hello, World!"? Código COS: 

Write "Hello, World!"

Crearemos una macro llamada HW que escribirá esta línea:

#define HW Write "Hello, World!"

Todo lo que necesitamos hacer ahora es escribir $$$HW ($$$ para llamar a la macro, luego su nombre):

ClassMethod Test()
{
     #define HW Write "Hello, World!"
     $$$HW
}

Se convertirá en el siguiente código INT durante la compilación:

zTest1() public {
     Write "Hello, World!" }

El siguiente texto se mostrará en la terminal cuando se llame a este método:

Hello, World!

Ejemplo 2

Usemos variables en el siguiente ejemplo:

ClassMethod Test2()
{
     #define WriteLn(%str,%cnt) For ##Unique(new)=1:1:%cnt { ##Continue
         Write %str,! ##Continue
     }
 $$$WriteLn("Hello, World!",5)

}

Aquí la cadena %str está escrita %cnt veces. Los nombres de las variables deben comenzar con %. El comando ##Unique(new) crea una nueva variable única en el código generado, mientras que el comando ##Continue nos permite continuar definiendo la macro en la siguiente línea. Este código se convierte en el siguiente código INT:

zTest2() public {
     For %mmmu1=1:1:5 {
         Write "Hello, World!",!
     } }

El terminal mostrará lo siguiente:

Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

 

Ejemplo 3

Pasemos a los ejemplos más complejos. El operador ForEach puede ser muy útil para iterar a través de globals, creémoslo:

ClassMethod Test3()
{
    #define ForEach(%key,%gn) Set ##Unique(new)=$name(%gn) ##Continue
    Set %key="" ##Continue
    For { ##Continue
        Set %key=$o(@##Unique(old)@(%key)) ##Continue
        Quit:%key=""
#define EndFor    }

   Set ^test(1)=111
   Set ^test(2)=222
   Set ^test(3)=333
   
   $$$EachFor(key,^test)
       Write "key: ",key,!
       Write "value: ",^test(key),!
   $$$EndFor

}

Así es como se ve en el código INT:

zTest3() public {
       Set ^test(1)=111
       Set ^test(2)=222
       Set ^test(3)=333
       Set %mmmu1=$name(^test)
       Set key=""
       For {
           Set key=$o(@%mmmu1@(key))
           Quit:key=""
           Write "key: ",key,!
           Write "value: ",^test(key),!
       } }

¿Qué está pasando en estas macros?

  1. Escribe el nombre del global a una nueva variable %mmmu1 (función $name )
  2. La clave asume el valor inicial de cadena vacía
  3. Comienza el ciclo de iteración
  4. El siguiente valor de la clave se asigna usando las funciones indirection y $order
  5. Post-condition se utiliza para verificar si la clave ha asumido un valor "" ; si es así, la iteración se completa y el ciclo termina
  6. Se ejecuta código de usuario arbitrario, en este caso, salida de clave y valor
  7. Se cierra el ciclo

El terminal muestra lo siguiente cuando se llama a este método:

key: 1
value: 111
key: 2
value: 222
key: 3
value: 333

Si está utilizando listas y matrices heredadas de la clase %Collection.AbstractIterator, puede escribir un iterador similar para ello.

Ejemplo 4

Otra capacidad de las macros es la ejecución de código arbitrario de ObjectScript en la etapa de compilación y la sustitución de sus resultados en lugar de una macro. Creemos una macro para mostrar el tiempo de compilación:

ClassMethod Test4()
{
      #Define CompTS ##Expression("""Compiled: " _ $ZDATETIME($HOROLOG) _ """,!")
      Write $$$CompTS
}

Que se transforma en el siguiente código INT:

zTest4() public {
      Write "Compiled: 18.10.2016 15:28:45",! }

El terminal mostrará la siguiente línea cuando se llame a este método:

Compiled: 18.10.2015 15:28:45

##Expression ejecuta el código y sustituye el resultado. Los siguientes elementos del lenguaje ObjectScript se pueden utilizar para la entrada:

  • Strings: "abc"
  • Routines: $$Label^Routine
  • Class methods: ##class(App.Test).GetString()
  • Funciones COS: $name(var)
  • Y combinaciones de estos elementos

Ejemplo 5

Directivas del pre procesador #If, #ElseIf, #Else, #EndIf se utilizan para seleccionar el código fuente durante la compilación, según el valor de la expresión que sigue una directiva. Por ejemplo, este método:

ClassMethod Test5()
{
    #If $SYSTEM.Version.GetNumber()="2016.2.0" && $SYSTEM.Version.GetBuildNumber()="736"
        Write "You are using the latest released version of Caché"
    #ElseIf $SYSTEM.Version.GetNumber()="2017.1.0"
        Write "You are using the latest beta version of Caché"
    #Else
        Write "Please consider an upgrade"
    #EndIf
}

Se compilará en el siguiente código INT en Caché versión 2016.2.0.736:

zTest5() public {
   Write "You are using the latest released version of Caché"
}

Y lo siguiente se mostrará en la terminal:

You are using the latest released version of Caché

Si usamos Caché descargado del portal beta, el código INT compilado tendrá un aspecto diferente:

zTest5() public {
    Write "You are using the latest beta version of Caché"
}

Lo siguiente se mostrará en la terminal:

You are using the latest beta version of Caché

Las versiones anteriores de Caché compilarán el siguiente código INT con una sugerencia para actualizar el programa:

zTest5() public {
    Write "Please consider an upgrade"
}

El terminal mostrará el siguiente texto:

Please consider an upgrade

Esta capacidad puede ser útil, por ejemplo, en situaciones en las que desea garantizar la compatibilidad de la aplicación cliente con versiones anteriores y nuevas, donde se pueden utilizar las nuevas características de Caché. Directivas del pre procesador #IfDef, #IfNDef tienen el mismo propósito al verificar la existencia o ausencia de una macro, respectivamente.

Conclusiones

Las macros pueden hacer que su código sea más legible al simplificar las construcciones de uso frecuente y ayudarlo a implementar parte de la lógica de negocios de su aplicación en la etapa de compilación, reduciendo así la carga en tiempo de ejecución.

Enlaces

0
0 340
Artículo Jose-Tomas Salvador · mayo 1, 2020 8m read
Era el momento del InterSystems hackathon y nuestro equipo, Artem Viznyuk y Eduard Lebedyuk tenian una placa Arduino (one) y varios componentes (de sobra). Así que su curso de acción estaba marcado - como todos los aprendices de Arduino, decidieron construir una estación meteorológica. Voy a aprovechar este artículo para seguir sus pasos y hacer lo mismo que ellos hicieron en 2016, pero con la persistencia de datos en IRIS y la visualización en Business Intelligence (antiguo DeepSee)! (Digamos que además de hacer la traducción del artículo original, aprovecho y nos actualizamos todos ;-) )

0
0 465
Artículo Mathew Lambert · feb 21, 2020 1m read

Estaba buscando la forma mas simple de conectar desde el visual studio code a mi instancia local por el terminal sin tener que ir cambiando de ventana.

Soy consciente de que esto tambien se puede conseguir por telnet pero me parece complicar la cosa para conectarme a mi local.

La solución mas sencilla me ha parecido navegar a la carpeta /bin de la instalación (o añadirla al PATH), y ejecutar .\csession.exe NOMBREDEINSTANCIA.

De hecho si tienes añadidas instancias remotas como conexiones, también se puede acceder a ellas.

Eso es todo!

0
0 278
Artículo Nancy Martínez · ene 20, 2020 5m read

¡Hola Comunidad!

HealthShare utiliza muchas transformaciones XSL. Estas transformaciones se utilizan para convertir los documentos médicos de la iniciativa “Integración de las Empresas Sanitarias (IHE)” en SDA (formatos interno de HealthShare), y convertirlos nuevamente en los formatos IHE, con el fin de crear resúmenes de los informes y para lidiar con los perfiles en el IHE (por ejemplo, consultar la información de los pacientes, proporcionar documentos y registrarlos). Los clientes pueden configurar las XSLT para personalizar los informes, o para utilizarlas de alguna otra manera.

Para la depuración y el desarrollo es muy conveniente que se pueda ejecutar un XSLT desde el Terminal.

0
0 226
Artículo Alberto Fuentes · ene 7, 2020 2m read

¡Hola Comunidad!

El gestor de paquetes InterSystems Package Manager (ZPM) es una gran herramienta, pero es aún mejor si la puedes usar directamente en lugar de tener que instalarla.  

Hay varias formas de hacer esto, a continuación veremos una forma de tener un contenedor IRIS con ZPM instalado a través del Dockerfile.

Hemos preparado un ejemplo con algunas líneas en el Dockerfile que se ocupan de la descarga e instalación de la última versión de ZPM
Añade estas líneas a tu Dockerfile estándar que utiliza el IRIS Community y tendrás ZPM instalado y listo para usar.

Para descargar la última versión del cliente ZPM:

0
0 247
Artículo Robert Cemper · dic 21, 2019 2m read

Para aquellos expertos que no pueden parar después del concurso "Advent of Code" (AoC2019), he publicado un código bastante antiguo en estilo tradicional para mejorarlo.

Fue escrito en base a una prueba previa en .XLS. Está lejos de ser perfecto. Es más bien un desafío para mejora en todas las direcciones (código, interfaz, ...). Así que cualquiera está invitado a mejorarlo.

0
0 223
Artículo Ricardo Paiva · nov 14, 2019 15m read
¡Hola Comunidad!

Suponga que desarrolló su propia aplicación con la tecnología de InterSystems y ahora quiere realizar varias implementaciones en sus distintos clientes. Durante el proceso de desarrollo usted escribió una guía de instalación detallada para aplicarla, ya que no solo necesita importar clases, también configurar el entorno de acuerdo a sus necesidades. 

Para atender esta tarea específica, InterSystems creó una herramienta especial llamada %Installer. Siga con la lectura para saber cómo utilizarla.

0
0 400
Artículo Mario Sanchez Macias · sep 26, 2019 8m read

¡Hola a todos!

En esta publicación me gustaría hablar sobre la tabla syslog: qué es, cómo analizarla, cuáles son realmente las entradas y por qué puede ser importante para usted. La tabla syslog puede contener información de diagnóstico importante. Si su sistema tiene algún problema, es importante entender cómo analizar esta tabla y qué información contiene.

<--break->¿Qué es una tabla syslog?

0
0 554
Pregunta Nancy Martínez · ago 5, 2019

¡Hola desarrolladores!

Programando a diario con IRIS y Docker, en el terminal VSCode llamo a los siguientes 3 comandos. Siempre de la misma forma para todos los proyectos:

docker-compose build   ; para compilar el contenedor

docker-compose up -d   ; para ejecutar IRIS en el contenedor

docker-compose exec iris iris session iris ; para abrir el terminal de IRIS

¿Hay alguna forma de acceso rápido por teclado que me escriba el resto?

1
0 264
Artículo David Reche · jul 16, 2019 2m read


Atelier necesita como mínimo la versión de Java 1.8 para su ejecución. pero manejar diferentes versiones de Java puede ser algo enredada en OSX (Mac)

En este artículo trato de explicar cómo manejar diferentes versiones de Java en el Mac.

El siguiente comando nos puede ayudar a aclarar algunos problemas en nuestro entorno:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (3):
  1.8.0_60, x86_64:    "Java SE 8"    /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home
  1.6.0_65-b14-466.1, x86_64:    "Java SE 6"    /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
  1.6.0_65-b14-466.1, i386:    "Java SE 6"    /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home​
0
0 2129
Artículo Bernardo Linarez · jul 1, 2019 16m read

Como todos sabemos, IRIS Database / Caché es un motor de base de datos que efectúa muchas tareas dentro de sí misma. Sin embargo, ¿qué puede hacer cuando necesita tener acceso a una base de datos externa? Una opción es utilizar el SQL Gateway en Caché mediante un conector JDBC. En este artículo, mi objetivo es responder las siguientes preguntas con el fin de ayudarle a que se familiarice con la tecnología y que resuelva algunos de los más problemascomunes.

0
1 886