Limpiar filtro
1.2K Publicaciones•4 Seguidores
173 Publicaciones•4 Seguidores
10 Publicaciones•0 Seguidores
Anuncio
David Reche · 25 jun, 2019
¡Hola Comunidad!Hay una funcionalidad nueva en la comunidad: Mejores Prácticas para InterSystems Data Platforms.Con esta etiqueta, resaltaremos los artículos de la Comunidad considerados como una Buena Práctica sobre cómo desarrollar, probar, desplegar y gestionar sobre InterSystems Data Platforms. ¿Por qué hacemos esto?A menudo nos preguntáis (a InterSystems) cuál es la diferente actitud respecto a una publicación, cómo distinguir publicaciones con mensajes de InterSystems para los desarrolladores de publicaciones que son "tan solo ideas". Actualmente, cada miembro de la Comunidad puede suscribirse para recibir las publicaciones de Product Managers y Technology Architects directamente, pero hay un montón de artículos de otros miembros de la comunidad que tienen mucha experiencia, conocimiento y soluciones brillantes, y que también son mejores prácticas para InterSystems Data Platforms. Y queremos dar valor a ese conocimiento.¿Quién toma esta decisión? Hemos establecido un grupo de Product Managers y Technology Architects de InterSystems que revisarán los artículos y decidirán si la publicación merece ser marcada como "Mejores Prácticas" de InterSystems.¿Qué publicaciones serán revisadas?Todos los artículos y algunas preguntas que tengan respuestas consideradas como buenas prácticas.¿Con qué frecuencia veremos "Mejores Prácticas" en la Comunidad?Cada semana etiquetaremos una nueva publicación como "Mejores Prácticas". Puedes recibir notificaciones sobre ellas si te suscribes a esa etiqueta. Además, en cada publicación añadiremos un comentario indicando que ha sido etiquetada como "Mejores Prácticas".¿Cuándo empezamos?¡Ya lo hemos hecho! ¡Suscríbete a la etiqueta y recibirás las "Mejores Prácticas" de InterSystems en tu email!¡Quedamos a la espera de sus artículos, que seguro serán "Mejores Prácticas"!
Anuncio
David Reche · 13 mar, 2020
En nombre de @John.Paladino, Vicepresidente de Servicios al Cliente, os hago llegar el comunicado oficial de InterSystems sobre el COVID-19:
"A la luz de la situación mundial provocada por el COVID-19, InterSystems está trabajando para asegurar el soporte continuo de nuestros clientes, garantizar la salud y el bienestar de nuestros empleados y proteger las comunidades en las que vivimos y trabajamos. Podéis leer nuestro comunicado oficial completo y las preguntas frecuentes sobre el COVID-19.
Además, hemos creado una dirección de email oficial, COVID-19@InterSystems.com, para resolver cualquier pregunta o preocupación.
Como hemos hecho durante 41 años, mantenemos nuestro compromiso con los clientes y los empleados y estamos preparados para apoyaros durante este difícil momento.
Un cordial saludo.
John Paladino
Vice President, Client Services"
Artículo
Kurro Lopez · 17 mayo, 2020
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:
El compilador de clases usa definiciones de clase para generar código MAC
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
El compilador de clases también genera un descriptor de clase utilizado por Caché en tiempo de ejecución
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
Todos estos cambios tienen lugar en la memoria; el código del usuario permanece sin cambios
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
El código INT es compacto y puede ser leído por un humano. Para verlo en el Studio, presione Ctrl + Shift + V.
El código INT se usa para generar código OBJ
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)
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?
Escribe el nombre del global a una nueva variable %mmmu1 (función $name )
La clave asume el valor inicial de cadena vacía
Comienza el ciclo de iteración
El siguiente valor de la clave se asigna usando las funciones indirection y $order
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
Se ejecuta código de usuario arbitrario, en este caso, salida de clave y valor
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
Acerca de la compilación
Lista de directivas de preprocesador
Lista de macros del sistema
Clase con ejemplos de este artículo.
Artículo
Ricardo Paiva · 17 jul, 2020
¡Hola desarrolladores!
Apuesto a que no todos los que estáis familiarizados con InterSystems Caché conocéis las extensiones de Studio para trabajar con el código fuente. De hecho, podéis usar Studio para crear vuestro propio tipo de código fuente, compilarlo en código de objeto e interpretable (INT) y a veces hasta añadir soporte para finalización de código. Es decir, teóricamente podéis hacer que Studio acepte cualquier lenguaje de programación a ejecutar por el DBMS (Sistema de Administración de Bases de Datos), así como Caché ObjectScript. En este artículo, os mostraré un ejemplo sencillo de cómo escribir programas en Caché Studio usando un lenguaje similar a JavaScript. Si os interesa, seguid leyendo.
Si vais al namespace SAMPLES, encontraréis un ejemplo de trabajo con tipos de archivo definidos por el usuario. El ejemplo sugiere abrir un documento del tipo “Example User Document (.tst)” type, y solo hay un archivo de este tipo llamado TestRoutine.TST, que, de hecho, se genera sobre la marcha. La clase requerida para trabajar con este tipo de archivo se llama Studio.ExampleDocument. No vamos a entrar en detalle en este ejemplo y vamos a crear uno propio. El tipo de archivo ".JS" ya está siendo usado en Studio, y el JavaScript que queremos soportar no es exactamente el JavaScript original. Vamos a llamarle CacheJavaScript y el tipo de archivo será ".CJS". Para empezar, cread una clase %CJS.StudioRoutines como subclase de la clase %Studio.AbstractDocument y añadidle el soporte del nuevo archivo.
/// El nombre de la extensión, puede ser una lista de extensiones separadas por coma si esta clase acepta más de una
Projection RegisterExtension As %Projection.StudioDocument(DocumentDescription = "CachéJavaScript Routine", DocumentExtension = "cjs", DocumentIcon = 1, DocumentType = "JS");
DocumentDescription — se muestra como la descripción del tipo en la ventana de abrir archivo en la lista de filtros;
DocumentExtension — la extensión de los archivos que serán procesados por esta clase;
DocumentIcon — el número de icono empieza en cero; los siguientes iconos están disponibles:
DocumentType — este tipo se usará para resaltar código y errores; están disponibles los siguientes tipos:
INT — código INT de Cache Object Script
MAC — código MAC de Cache Object Script
INC — incluir macro en Cache Object Script
CSP — página de servidor Cache (Cache Server Page)
CSR — regla de servidor Cache (Cache Server Rule)
JS — código JavaScript
CSS — hoja de estilo HTML
XML — documento XML
XSL — transformación XML
XSD — esquema XML
MVB — código mvb básico multivalor
MVI — código mvi básico multivalor
Ahora implementaremos todos los métodos necesarios para soportar el nuevo tipo de código fuente en Studio.
Los métodos ListExecute y ListFetch se usan para obtener una lista de archivos disponibles en el namespace y para mostrarlos en el diálogo de abrir archivo.
ClassMethod ListExecute(ByRef qHandle As %Binary, Directory As %String, Flat As %Boolean, System As %Boolean) As %Status
{
Set qHandle=$listbuild(Directory,Flat,System,"")
Quit $$$OK
}
ClassMethod ListFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = ListExecute ]
{
Set Row="",AtEnd=0
If qHandle="" Set AtEnd=1 Quit $$$OK
If $list(qHandle)'=""||($list(qHandle,4)=1) Set AtEnd=1 Quit $$$OK
set AtEnd=1
Set rtnName=$listget(qHandle,5)
For {
Set rtnName=$order(^rCJS(rtnName)) Quit:rtnName=""
continue:$get(^rCJS(rtnName,«LANG»))'=«CJS»
set timeStamp=$zdatetime($get(^rCJS(rtnName,0)),3)
set size=+$get(^rCJS(rtnName,0,«SIZE»))
Set Row=$listbuild(rtnName_".cjs",timeStamp,size,"")
set AtEnd=0
set $list(qHandle,5)=rtnName
Quit
}
Quit $$$OK
}
Guardaremos la descripción de los programas en el global ^rCJS, y el método ListFetch recorrerá este global para devolver cadenas que tengan lo siguiente: nombre, fecha y tamaño del archivo encontrado. Para que los resultados se muestren en el cuadro de diálogo, deberéis crear un método Exists que compruebe si existe un archivo con ese nombre.
/// Devolver 1 si existe la rutina 'name' y 0 si no existe.
ClassMethod Exists(name As %String) As %Boolean
{
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Set rtnNameExt = $piece(name,".",$length(name,"."))
Quit $data(^rCJS(rtnName))&&($get(^rCJS(rtnName,«LANG»))=$zconvert(rtnNameExt,«U»))
}
El TimeStamp devolverá la fecha y hora del programa. El resultado también se muestra en el cuadro de diálogo de abrir archivo.
/// Devolver el registro de la hora de la rutina 'name' en formato %TimeStamp. Esto se usa para determinar si la rutina ha
/// sido actualizada en el servidor y por tanto debe volver a cargarse desde Studio. Entonces el formato debería ser $zdatetime($horolog,3),
/// o "" si la rutina no existe.
ClassMethod TimeStamp(name As %String) As %TimeStamp
{
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Set timeStamp=$zdatetime($get(^rCJS(rtnName,0)),3)
Quit timeStamp
}
Ahora tendremos que cargar el programa y guardar los cambios en el archivo. El texto del programs, línea a línea, se guarda en el mismo global ^rCJS.
/// Cargar la rutina en Name hacia el flujo Code
Method Load() As %Status
{
set source=..Code
do source.Clear()
set pCodeGN=$name(^rCJS(..ShortName,0))
for pLine=1:1:$get(@pCodeGN@(0),0) {
do source.WriteLine(@pCodeGN@(pLine))
}
do source.Rewind()
Quit $$$OK
}
/// Guardar la rutina almacenada en Code
Method Save() As %Status
{
set pCodeGN=$name(^rCJS(..ShortName,0))
kill @pCodeGN
set @pCodeGN=$ztimestamp
Set ..Code.LineTerminator=$char(13,10)
set source=..Code
do source.Rewind()
WHILE '(source.AtEnd) {
set pCodeLine=source.ReadLine()
set @pCodeGN@($increment(@pCodeGN@(0)))=pCodeLine
}
set @pCodeGN@(«SIZE»)=..Code.Size
Quit $$$OK
}
Ahora viene la parte más interesante: compilar nuestro programa. Lo compilaremos en código INT y así tenemos una compatibilidad total con Caché. Este artículo es tan solo un ejemplo, y por eso usé solo una pequeña fracción de las funcionalidades de CachéJavaScript: declaración de variables (var), lectura (read), y salida de datos (println).
/// CompileDocument se llama cuando se quiere compilar el documento
/// En este punto, ya ha llamado a los hooks del control de fuente
Method CompileDocument(ByRef qstruct As %String) As %Status
{
Write !,«Compile: „,..Name
Set compiledCode=##class(%Routine).%OpenId(..ShortName_“.INT»)
Set compiledCode.Generated=1
do compiledCode.Clear()
do compiledCode.WriteLine(" ;generated at "_$zdatetime($ztimestamp,3))
do ..GenerateIntCode(compiledCode)
do compiledCode.%Save()
do compiledCode.Compile()
Quit $$$OK
}
Method GenerateIntCode(aCode) [ Internal ]
{
set varMatcher=##class(%Regex.Matcher).%New("[ \t]*(var[ \t]+)?(\w[\w\d]*)[ \t]*(\=[ \t]*(.*))?")
set printlnMatcher=##class(%Regex.Matcher).%New("[ \t]*(?:console\.log|println)\(([^\)]+)\)?")
set readMatcher=##class(%Regex.Matcher).%New("[ \t]*read\((.*)\,(.*)\)")
set source=..Code
do source.Rewind()
while 'source.AtEnd {
set tLine=source.ReadLine()
set pos=1
while $locate(tLine,"(([^\'\""\;\r\n]|[\'\""][^\'\""]*[\'\""])+)",pos,pos,tCode) {
set tPos=1
if $zstrip(tCode,"*W")="" {
do aCode.WriteLine(tCode)
continue
}
if varMatcher.Match(tCode) {
set varName=varMatcher.Group(2)
if varMatcher.Group(1)'="" {
do aCode.WriteLine($char(9)_«new „_varName)
}
if varMatcher.Group(3)'=“» {
set expr=varMatcher.Group(4)
set expr=..Expression(expr)
do:expr'="" aCode.WriteLine($char(9)_«set „_varName_“ = „_expr)
}
continue
} elseif printlnMatcher.Match(tCode) {
set expr=printlnMatcher.Group(1)
set expr=..Expression(expr)
do:expr'=“» aCode.WriteLine($char(9)_«Write „_expr_“,!»)
} elseif readMatcher.Match(tCode) {
set expr=readMatcher.Group(1)
set expr=..Expression(expr)
set var=readMatcher.Group(2)
do:expr'="" aCode.WriteLine($char(9)_«read „_expr_“,»_var_",!")
}
}
}
}
ClassMethod Expression(tExpr) As %String
{
set matchers($increment(matchers),«matcher»)="(?sm)([^\'\""]*)\+[ \t]*(?:\""([^\""]*)\""|\'([^\']*)\')([^\'\""]*)"
set matchers(matchers,«replacement»)="$1_""$2$3""$4"
set matchers($increment(matchers),«matcher»)="(?sm)([^\'\""]*)(?:\""([^\""]*)\""|\'([^\']*)\')[ \t]*\+([^\'\""]*)"
set matchers(matchers,«replacement»)="$1""$2$3""_$4"
set matchers($increment(matchers),«matcher»)="(?sm)([^\'\""]*)(?:\""([^\""]*)\""|\'([^\']*)\')([^\'\""]*)"
set matchers(matchers,«replacement»)="$1""$2$3""$4"
set tResult=tExpr
for i=1:1:matchers {
set matcher=##class(%Regex.Matcher).%New(matchers(i,«matcher»))
set replacement=$get(matchers(i,«replacement»))
set matcher.Text=tResult
set tResult=matcher.ReplaceAll(replacement)
}
quit tResult
}
Podéis ver el código INT generado para cada clase o programa compilado. Para ello, deberéis escribir un método GetOther. Es bastante simple: el objetivo es devolver una lista delimitada por comas de programas generados para el código fuente.
/// Devolver otros tipos de documentos con los que esto está relacionado.
/// Pasó un nombre y devolvéis una lista separada por comas de los otros documentos con los que está relacionado
/// o "" si no está relacionado con nada. Tened en cuenta que a esto se le puede pasar un documento de otro tipo
/// por ejemplo si vuestro documento 'test.XXX' crea una rutina 'test.INT', entonces también será llamado
/// con 'test.INT' para que podáis devolver 'test.XXX' para completar el ciclo.
ClassMethod GetOther(Name As %String) As %String
{
Set rtnName = $piece(Name,".",1,$length(Name,".")-1)_".INT"
Quit:##class(%Routine).%ExistsId(rtnName) rtnName
Quit ""
}
Implementamos un método para bloquear un programa de forma que solo un desarrollador a la vez pueda editar un programa o clase en el servidor.
No os olvidéis de escribir un método para eliminar programas.
/// Eliminar la rutina 'name', que incluye la extensión de rutina
ClassMethod Delete(name As %String) As %Status
{
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Kill ^rCJS(rtnName)
Quit $$$OK
}
/// Bloquear la rutina actual, el método predeterminado solo desbloquea el global ^rCJS con el nombre de la rutina.
/// Si eso falla, devolver entonces un código de estado del error. En caso contrario, devolver $$$OK
Method Lock(flags As %String) As %Status
{
Lock +^rCJS(..Name):0 Else Quit $$$ERROR($$$CanNotLockRoutine,..Name)
Quit $$$OK
}
/// Desbloquear la rutina actual, el método predeterminado solo desbloquea el global ^rCJS con el nombre de la rutina
Method Unlock(flags As %String) As %Status
{
Lock -^rCJS(..Name)
Quit $$$OK
}
Muy bien, hemos escrito una clase que nos permite trabajar con nuestro tipo de programas. Sin embargo, no podemos escribir dicho programa aún. Vamos a arreglarlo. Studio permite definir plantillas y hay 3 formas de hacerlo: un simple archivo CSP de un formato particular, una clase CSP heredada de la clase %CSP.StudioTemplateSuper y, finalmente, una página ZEN heredada de %ZEN.Template.studioTemplate. En nuestro caso, usaremos la última opción por simplicidad. Las plantillas pueden ser de 3 tipos también: para crear nuevos objetos, solo plantillas de código y complementos, que no generan salidas.
En nuestro caso, necesitaremos una plantilla para crear nuevos objetos. Creemos una nueva clase llamada %CJS.RoutineWizard. Su contenido es bastante simple: hay que describir un campo para introducir el nombre del programa y luego describir el nombre del nuevo programa y su contenido obligatorio para Studio en el método %OnTemplateAction.
/// Plantilla de Studio:
/// Crear una nueva rutina Cache JavaScript.
Class %CJS.RoutineWizard Extends %ZEN.Template.studioTemplate [ StorageStrategy = "" ]
{
Parameter TEMPLATENAME = "Cache JavaScript";
Parameter TEMPLATETITLE = "Cache JavaScript";
Parameter TEMPLATEDESCRIPTION = "Create a new Cache JavaScript routine.";
Parameter TEMPLATETYPE = "CJS";
/// Qué tipo de plantilla.
Parameter TEMPLATEMODE = "new";
/// Si en este caso TEMPLATEMODE="new" entonces este es el nombre de la pestaña
/// de Studio en la que se muestra esta plantilla. Si no se especifica ninguna, entonces
/// se muestra en la pestaña 'Custom'.
Parameter TEMPLATEGROUP As STRING;
/// Este bloque XML block define los contenidos del panel de contenido de esta plantilla de Studio.
XData templateBody [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
}
/// Proveer contenidos del componente de descripción.
Method %GetDescHTML(pSeed As %String) As %Status
{
Quit $$$OK
}
/// Esto se llama cuando la plantilla se muestra por primera vez;
/// Esto ofrece una oportunidad para definir el foco, etc.
ClientMethod onstartHandler() [ Language = javascript ]
{
// asignar foco al nombre
var ctrl = zenPage.getComponentById('ctrlRoutineName');
if (ctrl) {
ctrl.focus();
ctrl.select();
}
}
/// Controlador de validación para formulario incorporado en la plantilla.
ClientMethod formValidationHandler() [ Language = javascript ]
{
var rtnName = zenPage.getComponentById('ctrlRoutineName').getValue();
if ('' == rtnName) {
return false;
}
return true;
}
/// Este método es llamado cuando la plantilla está completa. Cualquier
/// salida al dispositivo principal es devuelta a Studio.
Method %OnTemplateAction() As %Status
{
Set tRoutineName = ..%GetValueByName("RoutineName")
Set %session.Data("Template","NAME") = tRoutineName_".CJS"
Write "// "_tRoutineName,!
Quit $$$OK
}
}
Y esto es todo. Ahora ya podéis crear vuestro primer programa escrito en Caché JavaScript en Studio.
Vamos a llamarlo “hello”.
El código fuente en CachéJavaScript puede verse así, por ejemplo:
// hello
console.log('Hello World!');
var name='';
read('What is your name? ', name);
println('Hello ' + name + '!');
Lo guardamos.
Después de guardar y compilar veremos que el código int también se generó y compiló con éxito, en la salida:
Compilation started on 11/04/2018 12:57:00 with qualifiers 'ck-u'
Compile: hello.CJS
Compiling routine : hello.int
Compilation finished successfully in 0.034s.
Veamos otra fuente.
Ahora podemos ejecutarlo en el terminal
USER>d ^hello
Hello World!
What is your name? daimor
Hello daimor!
Así es como podéis describir cualquier lenguaje (hasta cierto punto, por supuesto) que os guste y usarlo para codificar la lógica empresarial del lado del servidor para la plataforma de datos Caché/IRIS. Si este lenguaje no es compatible con Studio, habrá problemas con el resaltado de código. Este ejemplo demuestra el funcionamiento con programas, pero puede crear clases de Caché de la misma forma. Las posibilidades son casi infinitas: solo se necesita escribir un analizador léxico y un compilador completo, y luego diseñar el mapeo correcto entre todas las funciones del sistema Caché y las construcciones específicas del nuevo lenguaje. Este tipo de programas también pueden exportarse e importarse con la compilación, como se hace con muchos otros programas en Caché.
Quien quiera hacerlo en casa, puede descargar los códigos fuente aquí, en udl o xml.
Artículo
Ricardo Paiva · 13 mayo, 2021
> El orden es una necesidad para todos, pero no todos lo entienden de la misma manera (Fausto Cercignani)
*Nota de traducción: este articulo se publicó originalmente basado en Caché. Para esta traducción se revisó todo el contenido usando InterSystems IRIS.*
*Descargo de responsabilidad: En este artículo se utilizan el ruso y el alfabeto cirílico como ejemplos, pero esto solamente es importante para las personas que utilizan InterSystems IRIS en lugares en los que no se habla inglés.* *Ten en cuenta que este artículo se refiere principalmente a las compilaciones de NLS, que son diferentes a las compilaciones de SQL. Las compilaciones en SQL (por ejemplo, SQLUPPER, SQLSTRING, EXACT que significa que no hay compilación, TRUNCATE, etc.) son funciones reales que se aplican de manera explícita a algunos valores, y cuyos resultados a veces se almacenan explícitamente en los subíndices de los *globals*. De hecho, cuando se almacenan en subíndices, de forma natural estos valores seguirían la compilación de NLS (“[Compilaciones de SQL y NLS](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_basics#GSQL_basics_collation_sqlnls)”).*
En InterSystems IRIS, todo se almacena en *globals*: datos, metadatos, clases, rutinas. Los *globals* son persistentes. Los nodos de los *globals* se ordenan por los valores de los subíndices, y son almacenados en dispositivos de almacenamiento, sin un orden establecido de inserción, pero de forma ordenada para un mejor resultado en las búsquedas y disk fetch performance:
USER>set ^a(10)=""
USER>set ^a("фф")=""
USER>set ^a("бб")=""
USER>set ^a(2)=""
USER>zwrite ^a
^a(2)=""
^a(10)=""
^a("бб")=""
^a("фф")=""
Durante el proceso de clasificación, InterSystems IRIS distingue números y cadenas - 2 se maneja como un número y se clasifica antes que 10. El comando [ZWrite](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_czwrite) y las funciones [$Order](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_forder) y [$Query](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fquery) devuelven subíndices en el mismo orden en que se almacenan estos subíndices: primero se almacena una cadena vacía (la cual no se puede utilizar como subíndice), después los números negativos, cero, los números positivos, y luego las cadenas en el orden que se define en la compilación ([compilación](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GGBL_using#GGBL_using_sorting_collation)).
La compilación estándar en InterSystems IRIS se llama (como era de esperar) IRIS standard, y clasifica cada cadena de acuerdo a sus códigos de caracteres Unicode.
La compilación de las matrices locales en el proceso actual se define en local (Management Portal > System administration > Configuration > System Configuration > National Language Settings > Locale Definitions). La configuración local rusa para las instalaciones Unicode en InterSystems IRIS es rusw y la compilación predeterminada para rusw es Cyrillic3. Otras posibles compilaciones en la rusw local son IRIS standard, Cyrillic1, Cyrillic3, Cyrillic4, Ukrainian1.
ClassMethod [##class(%Collate).SetLocalName()](http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25Library.Collate#METHOD_SetLocalName) configura la compilación de las matrices locales en el proceso actual:
USER>write ##class(%Collate).GetLocalName()
Cyrillic3
USER>write ##class(%Collate).SetLocalName("IRIS standard")
1
USER>write ##class(%Collate).GetLocalName()
IRIS standard
USER>write ##class(%Collate).SetLocalName("Cyrillic3")
1
USER>write ##class(%Collate).GetLocalName()
Cyrillic3
Por cada compilación, hay una compilación alterna que clasifica los números como cadenas. El nombre de esa compilación contiene la variable “string” al final:
USER>write ##class(%Collate).SetLocalName("IRIS standard string")
1
USER>kill test
USER>set test(10) = "", test(2) = "", test("фф") = "", test("бб") = ""
USER>zwrite test
test(10)=""
test(2)=""
test("бб")=""
test("фф")=""
USER>write ##class(%Collate).SetLocalName("IRIS standard")
1
USER>kill test
USER>set test(10) = "", test(2) = "", test("фф") = "", test("бб") = ""
USER>zwrite test
test(2)=""
test(10)=""
test("бб")=""
test("фф")=""
IRIS standar y Cyrillic3
============================
IRIS standar clasifica los caracteres según sus códigos:
write ##class(%Library.Collate).SetLocalName("IRIS standard"),!
write ##class(%Library.Collate).GetLocalName(),!
set letters = "абвгдеёжзийклмнопрстуфхцчщщьыъэюя"
set letters = letters _ $zconvert(letters,"U")
kill test
//fill local array “test” with data
for i=1:1:$Length(letters) {
set test($Extract(letters,i)) = ""
}
//print test subscripts in sorted order
set l = "", cnt = 0
for {
set l = $Order(test(l))
quit:l=""
write l, " ", $Ascii(l),","
set cnt = cnt + 1
write:cnt#8=0 !
}
------------------------------
USER>do ^testcol
1
IRIS standard
Ё 1025,А 1040,Б 1041,В 1042,Г 1043,Д 1044,Е 1045,Ж 1046,
З 1047,И 1048,Й 1049,К 1050,Л 1051,М 1052,Н 1053,О 1054,
П 1055,Р 1056,С 1057,Т 1058,У 1059,Ф 1060,Х 1061,Ц 1062,
Ч 1063,Щ 1065,Ъ 1066,Ы 1067,Ь 1068,Э 1069,Ю 1070,Я 1071,
а 1072,б 1073,в 1074,г 1075,д 1076,е 1077,ж 1078,з 1079,
и 1080,й 1081,к 1082,л 1083,м 1084,н 1085,о 1086,п 1087,
р 1088,с 1089,т 1090,у 1091,ф 1092,х 1093,ц 1094,ч 1095,
щ 1097,ъ 1098,ы 1099,ь 1100,э 1101,ю 1102,я 1103,ё 1105,
Las letras cirílicas se imprimen en el mismo orden que aparecen en el alfabeto ruso, excepto la “ё” y la “Ё”. Sus códigos de caracteres Unicode están desordenados. “Ё” debe compilarse entre “Е” y “Д”, y “ё” entre “е” y “д”. Por eso la configuración local rusa necesita su propia compilación - Cyrillic3, que tiene las letras en el mismo orden que el alfabeto ruso:
USER>do ^testcol
1
Cyrillic3
А 1040,Б 1041,В 1042,Г 1043,Д 1044,Е 1045,Ё 1025,Ж 1046,
З 1047,И 1048,Й 1049,К 1050,Л 1051,М 1052,Н 1053,О 1054,
П 1055,Р 1056,С 1057,Т 1058,У 1059,Ф 1060,Х 1061,Ц 1062,
Ч 1063,Щ 1065,Ъ 1066,Ы 1067,Ь 1068,Э 1069,Ю 1070,Я 1071,
а 1072,б 1073,в 1074,г 1075,д 1076,е 1077,ё 1105,ж 1078,
з 1079,и 1080,й 1081,к 1082,л 1083,м 1084,н 1085,о 1086,
п 1087,р 1088,с 1089,т 1090,у 1091,ф 1092,х 1093,ц 1094,
ч 1095,щ 1097,ъ 1098,ы 1099,ь 1100,э 1101,ю 1102,я 1103,
Caché ObjectScript utiliza un operador binario especial ]] — «ordenar después». Devuelve el número 1, si el subíndice con el primer operador se ubica después del segundo operador, en caso contrario devuelve el número 0:
USER>write ##class(%Library.Collate).SetLocalName("IRIS standard"),!
1
USER>write "А" ]] "Ё"
1
USER>write ##class(%Library.Collate).SetLocalName("Cyrillic3"),!
1
USER>write "А" ]] "Ё"
0
*Globals* y compilaciones
======================
*Globals* diferentes en la misma base de datos pueden tener una compilación diferente. Cada base de datos tiene una opción de configuración - compilación predeterminada para los nuevos *globals*. Justo después de que se realiza la instalación, todas las bases de datos, excepto USER, utilizan la compilación predeterminada de IRIS standard. La compilación predeterminada para la base de datos USER se determina por la configuración local. Para rusw es Cyrillic3.
Para crear un *global* con una compilación que no sea la predeterminada para su base de datos, utiliza ##class(%GlobalEdit)##class(%GlobalEdit).Create method:
USER>kill ^a
USER>write ##class(%GlobalEdit).Create(,"a",##class(%Collate).DisplayToLogical("IRIS standard"))
Hay una columna de compilación para cada *global* en la lista de *globals* en el Management Portal (System Explorer > Globals).
No es posible cambiar la compilación de los *globals* actuales. Deberías crear un *global* con una nueva compilación y copiar los datos con el comando Merge. Para realizar la conversión masiva de *globals* utiliza [##class(SYS.Database).Copy()](http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=SYS.Database#METHOD_Copy)
Cyrillic4, Cyrillic3 y umlauts
==================================
Parece ser que convertir el subíndice de una cadena a un formato interno lleva, evidentemente, más tiempo con la compilación Cyrillic3 que con la compilación IRIS estándar. Por lo tanto, insertar y buscar la matriz global (o local) con la compilación Cyrillic3 es más lento. Caché 2014.1 incluye una nueva compilación - Cyrillic4, que tiene el mismo orden correcto de letras que Cyrillic3, y un mejor rendimiento.
for collation="IRIS standard","Cyrillic3","Cyrillic4" {
write ##class(%Library.Collate).SetLocalName(collation),!
write ##class(%Library.Collate).GetLocalName(),!
do test(100000)
}
quit
test(C)
set letters = "абвгдеёжзийклмнопрстуфхцчщщьыъэюя"
set letters = letters _ $zconvert(letters,"U")
kill test
write "test insert: "
//fill local array “test” with data
set z1=$zh
for c=1:1:C {
for i=1:1:$Length(letters) {
set test($Extract(letters,i)_"плюс длинное русское слово" _ $Extract(letters,i)) = ""
}
}
write $zh-z1,!
//looping through test subscripts
write "test $Order: "
set z1=$zh
for c=1:1:C {
set l = ""
for {
set l = $Order(test(l))
quit:l=""
}
}
write $zh-z1,!
----------------------
USER>do ^testcol
1
IRIS standard
test insert: 1.520673
test $Order: 2.062228
1
Cyrillic3
test insert: 3.541697
test $Order: 5.938042
1
Cyrillic4
test insert: 1.925205
test $Order: 2.834399
Cyrillic4 aún no es la compilación predeterminada para la configuración local rusw, pero puedes definir tu propia configuración local basada en rusw y especificar Cyrillic4 como compilación predeterminada para las matrices locales. O puedes configurar Cyrillic4 como la nueva compilación predeterminada para los *globals* en la configuración de la base de datos.
Cyrillic3 es más lento que IRIS estándar y Cyrillic4, porque se basa en un algoritmo más general que clasificar dos cadenas basándose en códigos de caracteres individuales.
En alemán, [la letra ß debería compilarse como ss](https://en.wikipedia.org/wiki/German_orthography#Sorting) durante el proceso de clasificación. InterSystems IRIS respeta esa regla:
USER>write ##class(%Collate).GetLocalName()
German3
USER>set test("Straßer")=1
USER>set test("Strasser")=1
USER>set test("Straster")=1
USER>zwrite test
test("Strasser")=1
test("Straßer")=1
test("Straster")=1
Ten en cuenta que la clasificación ordena las cadenas en subíndices. Específicamente, las primeras cuatro letras de la primera cadena son “Stras”, después “Straß”, y otra vez “Stras”. Es imposible clasificar las cadenas de esa manera, si la compilación solo es una clasificación basada en los códigos de caracteres separados.
Otro ejemplo es el finlandés, donde [“v” y “w” deben compilarse como la misma letra](https://en.wikipedia.org/wiki/Finnish_orthography#Collation_order). Las reglas para compilar el idioma ruso son más simples: a cada letra se le asigna un código específico y la clasificación mediante estos códigos es suficiente. Eso permitió mejorar el rendimiento de la compilación Cyrillic4 sobre Cyrillic3.
Compilación y SQL
==================
No hay que confundir la compilación de una matriz con la compilación de SQL. Esta última es la conversión que se implementa en la cadena antes de que realice una comparación, o que se utilice como subíndice en el índice global. SQLUPPER es la compilación predeterminada de SQL en InterSystems IRIS. En esta compilación todos los caracteres se convierten en mayúsculas, se eliminan los caracteres de espacio y se añade un espacio al inicio de la cadena. Otras compilaciones SQL (EXACT, SQLSTRING, TRUNCATE) se describen en [la documentación](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_basics#GSQL_basics_collation).
Es fácil complicar las cosas cuando diferentes *globals* en la misma base de datos tienen diferente compilación, y las matrices locales tienen otra compilación. SQL utiliza la base de datos IRISTEMP para los datos temporales. La compilación predeterminada para los *globals* en IRISTEMP puede ser diferente de la compilación para la configuración local de InterSystems IRIS.
Hay una regla principal - para que las consultas ORDER BY en SQL devuelvan las filas en el orden esperado, la compilación de los *globals* donde se almacenan los datos y los índices de las tablas relevantes deben ser la misma que la compilación predeterminada de la base de datos IRISTEMP y la compilación de las matrices locales. Para obtener más información, consulta el párrafo en la documentación “[Compilaciones de SQL y NLS](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_basics#GSQL_basics_collation_sqlnls)”.
Vamos a crear la clase de prueba:
Class Collation.test Extends %Persistent
{
Property Name As %String;
Property Surname As %String;
Index SurInd On Surname;
ClassMethod populate()
{
do ..%KillExtent()
set t = ..%New()
set t.Name = "Павел", t.Surname = "Ёлкин"
write t.%Save()
set t = ..%New()
set t.Name = "Пётр", t.Surname = "Иванов"
write t.%Save()
set t = ..%New()
set t.Name = "Прохор", t.Surname = "Александров"
write t.%Save()
}
}
Añade datos a la clase (más tarde puedes intentar utilizar las palabras del ejemplo anterior con el alemán):
USER>do ##class(Collation.test).populate()
Realiza la consulta:

Ese es el resultado inesperado. La pregunta principal es: ¿por qué los nombres no se ordenan alfabéticamente? (Павел, Пётр, Прохор)? Veamos el plan de consultas:

Las palabras clave de este plan son “populates temp-file”. El motor SQL decidió utilizar una estructura temporal para realizar esta consulta. Aunque se llama "file" ("archivo"), en realidad se trata de un *global* process-private y en algunos casos es una matriz local. Con los valores de los subíndices de este *global* se ordenarán, en este caso particular, nombres de personas. Los *globals* process-private se almacenan en la base de datos IRISTEMP y la clasificación predeterminada para los nuevas *globals* en IRISTEMP es IRIS estándar.
Otra pregunta razonable es por qué “ё” se devuelve a la parte superior y no a la inferior (recuerda, en IRIS estándar “ё” se clasifica después de todas las letras rusas; y “Ё”, antes). Los subíndices del *global* temporal no son el valor exacto del campo Name, sino los valores en mayúsculas de Name (SQLUPPER es [la compilación de SQL predeterminada para las cadenas](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_order#RSQL_C64334)), y, por tanto, devuelve “Ё” antes que otros caracteres.
Al modificar la compilación predeterminada mediante la función [%Exact](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_exact), todavía la recibiríamos de forma incorrecta, pero al menos “ё” se clasifica después de otras letras, como un resultado esperado.

Por el momento, no vamos a cambiar la compilación predeterminada de IRISTEMP - vamos a verificar las consultas con la columna Surname. El índice de esta columna se almacena en el *global* ^Collation.testI. La compilación de ese *global* es Cyrillic3, así que deberíamos ver el orden correcto de las filas:

Equivocado de nuevo — “Ё” debería ir entre “А” y “И”. Echa un vistazo al plan de consulta:

Los datos del índice no son suficientes para obtener los valores originales del campo Surname porque SQLUPPER se aplica a los valores del índice SurInd. El motor SQL decidió utilizar los valores de la propia tabla y ordenar los valores en el archivo temporal, tal como hizo antes con la columna Name.
En la consulta podemos indicar que estamos de acuerdo con que los apellidos se escriban en mayúsculas. El orden será el correcto porque las filas se tomarán directamente del índice global ^Collation.testI:

El plan de consulta es como se esperaba:

Ahora hagamos lo que deberíamos haber hecho hace mucho tiempo: cambiar la compilación predeterminada de la base de datos IRISTEMP a Cyrillic3 (o Cyrillic4).
Las consultas que utilizan archivos temporales darán como resultado filas en el orden correcto:


Resumen
===========
* Si no te interesan los matices de los alfabetos locales, utiliza la compilación IRIS estándar.
* Algunas compilaciones (Cyrillic4) tienen un mejor rendimiento que otras (Cyrillic3).
* Comprueba que IRISTEMP tiene la misma compilación que tu base de datos principal y matrices locales.
Nota de traducción: para ver una lista con las collations disponibles y las cargadas en la instancia, abre una ventana de Terminal, cambia al namespace % SYS% e ingresa el comando DO ^ COLLATE.
Artículo
Nancy Martínez · 2 feb, 2021
¿Qué es OData?
OData (Open Data Protocol) es un estándar OASIS, con certificación ISO/IEC, que define un conjunto de prácticas recomendadas para construir y consumir APIs RESTful. OData te ayuda a enfocarte en tu lógica de negocio mientras construyes APIs RESTful, sin tener que preocuparte por los diversos enfoques para definir cabeceras de solicitud y respuesta, códigos de estado, métodos HTTP, convenciones URL, tipos de medios audiovisuales, formatos de carga, opciones de consulta, etc. OData también proporciona orientación para registrar cambios, definir funciones/acciones para llevar a cabo procedimientos reutilizables y enviar solicitudes asíncronas/por lotes (Fuente: OData.org).
Casos de uso de OData
Desplegar datos como servicios REST con un formato interoperable, sin dificultades para desarrollarlos
Permite que la Inteligencia empresarial (BI), visualización de datos, ERP, CRM, ESB, herramientas y motores de flujo de trabajo consuman datos utilizando REST sin esfuerzos de desarrollo
Virtualiza datos corporativos en las herramientas de gestión de APIs
Promueve una forma estándar para implementar las API REST, que permite funcionalidades de consulta similares a las de SQL utilizando estas APIs RESTful. OData esencialmente SQL para entornos webs, desarrollados con protocolos estándar de nivel superior, HTTP, JSON y ATOM, al mismo tiempo que se aprovecha el estilo de la arquitectura REST (progress.com).
OData es ampliamente adoptado:
Ayuda a implementar FHIR: FHIR (Fast Healthcare Interoperability Resources) es un estándar para el intercambio electrónico de información relacionada con la atención sanitaria. Para que FHIR sea verdaderamente interoperable, se recomienda que los sistemas utilicen las reglas establecidas por las especificaciones de OData para el parámetro $search. Además, FHIR también utiliza OAuth para establecer una relación de confianza con el cliente para una capa adicional de seguridad (progress.com).
Soporta paginación, solicitudes por lotes y diferentes formatos como JSON, ATOM, XML, etc.
OData e InterSystems IRIS
InterSystems IRIS no es compatible con OData, pero es posible utilizar el servidor de OData para que InterSystems IRIS permita mostrar clases persistentes como REST.
Para ello, sigue estas instrucciones:
Clonar el código fuente del servidor IRIS OData: git clone https://github.com/yurimarx/isc-iris-odata.git
Ir a la carpeta: isc-iris-odata
Ejecutar: mvnw install (MS Windows) o ./mvnw install (Linux o Mac)
Ejecutar: docker build -t odata:1.0.0 .
Ejecutar: docker run -p 8080:8080 odata:1.0.0. Tu servidor OData iniciado:
Iniciar tu instancia de InterSystems IRIS con cualquier clase persistente
En navegador de acceso: http://localhost:8080/. Establecer los parámetros en la pantalla:
Estos son los parámetros para mi instancia. Establece los parámetros en tu instancia de IRIS. En el namespace establece tu namespace de iris; en el esquema, el esquema de la tabla SQL; y en el puerto, el puerto a tu conexión con la base de datos JDBC.
Hacer clic en Enviar y RECARGAR TU INSTANCIA DE DOCKER DE ODATA SERVER PARA APLICAR LOS PARÁMETROS.
Ir a: http://localhost:8080/odata.svc/ para ver todas las clases persistentes en tu esquema de IRIS. En mi caso es:
Para navegar hacia una clase persistente, usar: http://localhost:8080/odata.svc/<Persistent_Class>. Por ejemplo: http://localhost:8080/odata.svc/Animal
El servidor OData hace una lista con los datos Animales, mira:
Para verlo en formato JSON: http://localhost:8080/odata.svc/Animal?$format=application/json. Mira:
Para ver los detalles de una fila: http://localhost:8080/odata.svc/Animal(8)?$format=application/json
Para eliminar, envía un DELETE en tu postman con http://localhost:8080/odata.svc/Animal(8)
Para insertar, envía un POST en tu postman con http://localhost:8080/odata.svc/Animal y una estructura JSON con los nombres de las propiedades y pares de valores, como:
Así que puedes realizar todas las operaciones CRUD con tus clases persistentes.
Otras muchas funcionalidades estarán disponibles en el futuro, si IRIS OData Server obtiene la aceptación de la comunidad.
¡Gracias!
40 Publicaciones•0 Seguidores
0 Publicaciones•0 Seguidores
0 Publicaciones•0 Seguidores
Anuncio
David Reche · 7 abr, 2020
¡Hola desarrolladores!
¿Queréis participar de nuevo en un concurso y crear soluciones de código abierto con InterSystems IRIS Data Platform?
¡Ya hemos lanzado el segundo concurso para desarrolladores de InterSystems!
El tema de este concurso es InterSystems IRIS con REST-API.
El concurso estará activo durante tres semanas, del 13 de abril al 3 de mayo de 2020.
Premios
Hay dos categorías de premios y habrá más premios en metálico que en el primer concurso.
1. Nominación de los Expertos - los ganadores serán elegidos por un jurado especialmente formado para el concurso. Los premios serán:
🥇 1er puesto - $2,000
🥈 2º puesto - $1,000
🥉 3er puesto - $500
2. Nominación de la Comunidad - ganará la aplicación que obtenga el mayor número total de votos. Los premios serán:
🥇 1er puesto - $1,000
🥈 2º puesto - $500
Si dos o más participantes obtienen la misma cantidad de votos, todos serán considerados ganadores y el dinero del premio se repartirá entre todos.
Los ganadores también recibirán las insignias de mayor nivel del programa de fidelización Global Masters.
¿Quién puede participar?
Cualquier miembro registrado en la Comunidad de Desarrolladores de cualquier país puede participar en el concurso, excepto los empleados de InterSystems.
Jurado
Los miembros del jurado para la Nominación de Expertos serán Product Managers de InterSystems, moderadores de la Developer Community y embajadores de Global Masters con nivel VIP, Embajador, Experto y Especialista.
Cada miembro del jurado solo podrá votar por una aplicación. El valor de los votos es el siguiente:
Votos de los Product Managers - 3 puntos
Votos de los Moderadores - 3 puntos
Votos de los miembros de Global Master con nivel VIP - 3 puntos
Votos de los miembros de Global Master con nivel Embajador - 3 puntos
Votos de los miembros de Global Master con nivel Experto - 2 puntos
Votos de los miembros de Global Master con nivel Especialista - 1 punto
Hemos añadido miembros al jurado y ahora pueden votar los miembros de Global Master con nivel Especialista.
Los miembros del jurado para la Nominación de la Comunidad serán cualquier miembro registrado de la Comunidad, que al menos haya publicado una vez en la Comunidad y sus votos valdrán 1 punto.
Los miembros de los jurados pueden participar en el concurso, pero no podrán votar por sus propias aplicaciones.
Criterios del jurado
En la Nominación de los Expertos, se elegirá la aplicación que mejor cumpla los siguientes criterios:
Que haga del mundo un lugar mejor o que mejore la vida de los desarrolladores;
Que tenga la mejor funcionalidad - cuánto hace la librería/aplicación
Que tenga código ObjectScript legible y de calidad.
Duración del concurso
Del 13 al 26 de abril de 2020: Dos semanas para subir las aplicaciones a Open Exchange (durante este período, se podrán modificar los proyectos).
Del 27 de abril al 3 de mayo de 2020: Una semana para votar.
Los ganadores serán anunciados el día 4 de mayo de 2020.
Tema del concurso
➡️ InterSystems IRIS REST API y web socket applications ⬅️
Se elegirá la mejor aplicación desarrollada con InterSystems IRIS Community Edition (IRIS CE) o InterSystems IRIS for Health Community Edition (IRIS CE4H) como backend exponiendo APIs REST o interfaz Web sockets.
Requisitos de InterSystems REST API:
Si se clona o descarga la aplicación, debe ser ejecutable, por ejemplo, con:
$ docker-compose up -d
O instalada como un módulo ZPM, por ejemplo, como:
zpm:USER>install module-name
Una vez instalada, la aplicación REST API o Web Sockets debe estar disponible en localhost:anyport/your/application.
Bonus adicionales
Si la aplicación cumple unos requisitos tecnológicos adicionales, obtendrá puntos extra, uno por cada requisito que cumpla.
Estos son los bonus para este concurso:
Gestor de paquetes ZPM - La solución puede ser instalada a través de ZPM package;
Documentación Open API 2.0 (swagger), disponible en /_spec endpoint de tu REST API
Enfoque de especificación primero (Spec First) - API REST generada desde una especificación Swagger usando el servicio de Open API de InterSystems IRIS
Aplicación de ejemplo
Esta es la plantilla de aplicación de ejemplo objectscript-docker-rest-template
Una vez clonada, podría ejecutarse con el siguiente comando en el directorio de la aplicación:
$ docker-compose up -d
La aplicación expone REST API en localhost:port/crud, lo que permite crear, leer, actualizar y eliminar registros de una clase persistente de IRIS.
Obtiene un punto tecnológico extra porque también puede ser instalada como módulo ZPM con el comando:
zpm:USER>install rest-template
Y otro punto tecnológico porque expone una especificación swagger en localhost:port/crud/_spec.
Esta documentación está publicada aquí, lo que puede hacerse de forma automática con Postman.
Se puede usar esta aplicación como plantilla.
Así que... Ready. Set. Code.
¡Suerte a tod@s!
❗️Echa un vistazo a los Términos Oficiales del Concurso.❗️
¡Hola Comunidad!
Hemos lanzado un hashtag especial para nuestro maratón de concursos de programación: #IRIScontest
El hashtag ya se está usando en las redes sociales de InterSystems en inglés (Twitter, Facebook, Telegram y LinkedIn) y comenzaremos a usarlo desde hoy en las redes sociales en español (Twitter y LinkedIn).
Sigue el hashtag para estar al tanto de todas las novedades de los concursos
Han añadido un tercer punto tecnológico extra: uso de un enfoque de especificación primero.
Podrás obtener un punto extra si generas la API REST en IRIS con una especificación swagger usando el servicio de Open API. Consulta la documentación aquí.
Ejemplos: uno, dos, tres ¡Última semana para participar en el concurso!
Podeis ir echando un vistazo a las aplicaciones que ya se han presentado aquí: Contest Board
¡Animaos! ¡Esperamos vuestros proyectos!
Anuncio
Esther Sanchez · 24 abr, 2020
¡Hola Comunidad!
InterSystems ha lanzado “InterSystems IRIS Tech Talks”, una serie de webinars presentados por Product Managers de InterSystems.
Los webinars (todos en inglés) se sumergirán en las últimas funcionalidades y novedades de InterSystems IRIS 2020.1 desde el punto de vista de los desarrolladores. Irán más allá de las visiones generales y probarán las mejores y más recientes tecnologías que se lancen.
Estos son los webinars planeados para mayo y junio:
✅ API-First DevelopmentFecha: 5 de mayo, 2020Hora: 16:00 h. CEST (10:00 AM EDT)
✅ Integrated Development EnvironmentsFecha: 19 de mayo, 2020Hora: 16:00 h. CEST (10:00 AM EDT)
✅ DevOpsFecha: 2 de junio, 2020Hora: 16:00 h. CEST (10:00 AM EDT)
➡️ Ya podéis registraros aquí >>¡Os esperamos!
¡ Y ya podéis ver la grabación del primer webinar de la serie, que se celebró este martes pasado: Data Science, Machine Learning & Analytics !Registraos aquí para verlo >>
¡Esperamos que os resulte útil!
Anuncio
David Reche · 11 mayo, 2020
¡Hola desarrolladores!
¡Ya hemos lanzado el siguiente concurso para crear soluciones de código abierto utilizando InterSystems IRIS Data Platform!
¡Así que damos la bienvenida al tercer concurso de programación con InterSystems!
El tema de este concurso es API Nativa de InterSystems IRIS.
El concurso estará activo durante tres semanas: del 18 de mayo al 7 de junio de 2020.
Premios
1. Nominación de los expertos - los ganadores serán elegidos por un jurado especialmente formado para el concurso. Los premios serán:
🥇 1er puesto - $2,000
🥈 2º puesto - $1,000
🥉 3er puesto - $500
2. Nominación de la Comunidad - ganará la aplicación que obtenga el mayor número total de votos. Los premios serán:
🥇 1er puesto - $1,000
🥈 2º puesto - $500
Si dos o más participantes obtienen la misma cantidad de votos, todos serán considerados ganadores y el dinero del premio se repartirá entre todos.
Los ganadores también recibirán las insignias de mayor nivel del programa de fidelización Global Masters.
¿Quién puede participar?
Cualquier miembro registrado en la Comunidad de Desarrolladores de cualquier país puede participar en el concurso, excepto los empleados de InterSystems. Regístrate aquí en la Comunidad si aún no tienes una cuenta >>
Duración del concurso
Del 18 al 31 de mayo de 2020: Dos semanas para subir las aplicaciones a Open Exchange (durante este período, se podrán modificar los proyectos).
Del 1 al 7 de junio de 2020: Una semana para votar.
Los ganadores serán anunciados el día 8 de junio de 2020.
Tema del concurso
➡️ API Nativa de InterSystems IRIS ⬅️
Se elegirá la mejor aplicación que cumpla los requisitos de la API NATIVA DE IRIS. La aplicación puede ser una librería, paquete, herramienta o cualquier solución que utilice cualquiera de las APIs Nativas de InterSystems IRIS: .NET, Java, Python, Node.js. Aquí tienes más información sobre las APIs Nativas de InterSystems IRIS.
La aplicación debe funcionar en InterSystems IRIS Community Edition o en InterSystems IRIS for Health Community Edition.
La aplicación debe ser Open Source y publicarse en GitHub.
Y las aplicaciones que implementen unos requisitos tecnológicos adicionales, obtendrán bonus tecnológicos.
Bonus tecnológicos adicionales
1. Contenedor Docker - 1 punto extra
Si la aplicación usa InterSystems IRIS ejecutándose en un contenedor Docker, obtendrá este bonus.
Cuando se clone o descargue la aplicación, debe ser ejecutable con:
$ docker-compose up -d
Aplicaciones de muestraPlantilla para el concurso Native API - Demostración completa de configuración y puesta en marcha con 4 APIs disponibles. La plantilla cumple con el bonus tecnológico "Contenedor Docker".
Recursos adicionales
1. Cómo enviar una aplicación a un concurso: Vídeo
2. Empezar con InterSystems IRIS Native API: Java, .NET, Python and Node.js
3. Documentación sobre Native API: Python, Java, .NET, Node.js
3. Vídeos: InterSystems IRIS and Node.js, Globals Quickstart
4. Cursos online sobre Native API
Judgment
Consulta los Criterios del jurado y Reglas sobre los votos.
Así que... Ready. Set. Code.
¡Suerte a tod@s!
❗️ Echa un vistazo a los Términos Oficiales del Concurso.❗️ ¡Hola desarrolladores!
Hoy empieza el tercer concurso de programación con InterSystems IRIS.
Tenéis 2 semanas (hasta el domingo 31 de mayo) para subir vuestras soluciones a Open Exchange.
¡Animaos! ¡La gloria (y varios premios) os esperan!