Testing ECP-based applications often take quite some effort for setup and preparation.
I have created a Docker-based workbench that allows you to have it quick at hands.
And if you crash it? You just give your containers a fresh start.
The whole setup runs code-based during the start-up of your instance.
In that sense, it is also a portable coding example using ZPM and the objectscript-docker-template
Similar to Caché so also in IRIS, you have ClassQueries available in 2 variants
- Basic class queries, which use the class %SQLQuery and an SQL SELECT statement.
- Custom class queries, which use the class %Query and custom logic to execute, fetch, and close the query.
Migration from Caché to IRIS can be quite a challenge if your code is grown over many years
and probably not so clean structured as you may like it. So you face the need to check your
migrated code against some reference data. A few samples might not be a problem,
but some hundred GB of data for testing might be.
A possible step could be to have your fresh code in IRIS but leave your huge datastore on Caché and connect both environments over ECP. I have created a demo project that gives you the opportunity to try this based on 2 Docker images with IRIS and with Caché connected over ECP.
As you know ObjectScript has neither FOREACH system command nor system function.
But it has a wide room for creativity.
The task is to loop over a global or local array and do something FOR EACH element.
There are 2 possible solutions:
- creating a macro that generates the required code sequences
- creating an Extended Command to perform the action. Both ways are presented here. The macro is a generic and quite flexible solution and easy to adapt if required.
This is a demo to make use of a simple WebSocket Client with Embedded Python in IRIS.
How to Test it
- Run an Iris Session in Docker
- Select your WebSocket Echo Server
- Enter the text you want to send or generate it
- Send it and see the result
$ docker-compose exec iris iris session iris "##class(rccpy.WSockPy).Run()"
*** Welcome to WebSocket Embedded Python Demo ***
Collecting websocket-client
Using cached https://files.pythonhosted.org/packages/4c/5f/f61b420143ed1c8dc69f9eaec5ff1ac36109d52c80de49d66e0c36c3dfdf/websocket_client-0.57.0-py2.py3-none-any.
This is a first attempt to use Embedded Python in IRIS
The Python code is adapted from solutions for Advent of Code 2020 contest.
Test data are all input to my personal challenge.
Prerequisites
Make sure you have git and Docker desktop installed.
Installation
Clone/git pull this repo into any local directory
$ git clone https://github.
Every now and then you may encounter a situation where for various reasons
ODBC is the only option to access a remote system. Which is sufficient as long as you need to examine or change tables.
But you can't directly execute some commands or change some Global.
The demo is based on the raw class descriptions.
The data classes used are Address, Person, Employee, Company
For a more attractive demo, a JSONtoString method by ID was added.
It seems to me that for some reason this didn't make its way to the official documentation
and seems to be rather unknown though implemented already in IRIS 2020.1
Thanks to @Dan Pasco I got a hint on the classes involved.
I used the recommended sequence of how to use it.
it is all directly taken from Class Reference and I just collected it to create a first overview.
Caused by a conflict in the port assignment I get this entry in mesages.log and SMP doesn't respond:
08/30/20-12:56:40:737 (15232) 0 [Utility.Event] Private webserver started on 52773
The first line is true, the second is just wishful thinking ![]()
demo code on GitHub
Triggered by a question placed by @Kurro Lopez recently
I took a closer look at the indexing of collections.
My simple test setup is a serial class and a persistent class with a list of this serial.
In most cases, a global used by default storage has just 1 subscript level that represents the IDKEY.
For an index-globals we may see 2 or more subscript levels.
Arrays, or parent-child relationships or persistent classes extending a base data class
are examples where we see more levels. Though all these globals are quite uniform.

Globals in Caché / Ensemble / IRIS are normally invisible over SQL access
This example shows how to overcome this limit.
Standard error logs in IRIS / Caché / Ensemble are written global ^ERRORS.
As this piece dates back some decades back to previous millennium, its structure
is far from the typical SQL storage structures.
The offer of ZPM is growing daily and the short names and
acronyms of the offer are sometimes hard to understand and
also hard to type with my lazy fingers.
So I decided to have
- a listing with the descriptions from the repository,
- split in short junks to avoid backscroll,
- controlled forward / backward scrolling,
- the option to select my packages by number,
- to install or uninstall with limited typing.
It runs with do ^zpmshow
A snapshot from the screen:
USER>d ^zpmshow
1 analyzethis 1.1.4 -- not github --
2 apps.rest 1.0.0 -- no descripition --
3 bitmap-adoption 1.0.
During my search for a snapshot of a persistent object,
I met a feature that I would like to share as it could be useful in some special situations.
My trigger was to have a before- and an after-image during unit testing.
This is a sample to use %JSON.Adaptor class available in IRIS to produce a snapshot of your object.
The sample consists of 2 classes that are variations of what was known in Caché/SAMPLES as Sample.Person.
Be aware that the possibilities are limited by %JSON.Adapter and how you make use of it.
Once in place, you create some test data by Populate().
You select an object and take a snapshot.
You apply changes to your object and take another snapshot.
And see the difference.
BINGO!
It's also an example of a customized SystemFunction extension (ZZISJSON) in Caché & IRIS
This time it is to be included in %ZLANGF00.mac
A JSON string is mostly imported from a file or over REST
You rely on a clean and compatible structure. This is the check.
required: ZPretty.mac
demo
USER>ZWRITE jsn
jsn="{"Name":"Li,Robert K.","SSN":"672-92-9664","DOB":"1975-01-12","Home":{"Street":"986 Washington Blvd","City":"Boston","State":"PA","Zip":"95802"},"Office":{"Street":"6012 First Place","City":"Reston","State":"MT","Zip":"77739"},"Spouse":{"Name":"Avery,Zelda H.t's also an example for a customized command extension (ZZJSN) in Caché & IRIS
This is the Caché version for fast JSON formatting but it also works in IRIS.
Requires package ZPretty
To allow parallel existence in IRIS this is named ZZJSN
see:
USER>ZWRITE jsn
jsn="{"Name":"Li,Robert K.","SSN":"672-92-9664","DOB":"1975-01-12","Home":{"Street":"986 Washington Blvd","City":"Boston","State":"PA","Zip":"95802"},"Office":{"Street":"6012 First Place","City":"Reston","State":"MT","Zip":"77739"},"Spouse":{"Name":"Avery,Zelda H.t's also an example for a customized command extension (ZZJSON) in IRIS
IRIS has a nice %JSON.Formatter class.
But for debugging it is not really handy.
see:
ZWRITE js1
js1="{""Name"":""Cunningham,John C."",""SSN"":""294-11-9150"",""DOB"":""1933-01-08"",""Home"":{""Street"":""4249 Ash Street"",""City"":""Tampa"",""State"":""MD"",""Zip"":""30176""},""FavoriteColors"":\[""White"",""Red"",""Green""]}"
so you proceed for the most simple case
set formatter=##class(%JSON.Formatter).%New()
do formatter.Format(js1)
{
"Name":"Cunningham,John C.It is a classic Global Mapping exercise presenting ^SPOOL as Class / Table
Background
Device #2 named SPOOL dates back to the predecessors of Caché and IRIS
It was the first "%Stream" like option to buffer output before printing.
It is also the first and till today the most simple way of output redirection.
Solution
This is also an example of a mapped Global.
USE 2 redirects the output into the Global ^SPOOL
You can read the global manually or with some ancient utilities
or use this mapping to access it as class or a SQL table.
The guide “Extending Languages with %ZLANG Routines”
Tells you all details you need to know to extend your programming language.
EXCEPT: How to do it in a clean way.
This example of a %ZLANGC00.mac may show a possible approach
to get an easy to overview and to manage setup.
With less than 50 lines of code you might not be affected.
But if your Studio shows close to 1000 rows or more you may get in troubles.
My recommendation is simple.
Instead of adding line-by-line commands and it's code
you isolate each command and its code into a separate Include file.
IRIS and Caché / Ensemble offer the possibility to add Languages Extension as SystemFunctions, SystemVariables, SystemCommands
The related documentation tells you where to add the system-wide extension. Parameter passing is not covered explicitly.
During the development of the Terminal Multi-Line Command Editor I discovered in my IRIS installation
a piece of software that I just can classify as a historic artifact. And it is still fully operational !!!
As it dates back to times before InterSystems was founded in 1978 you may understand my surprise.
I personally stepped into that environment in 1978 and used it then for daily work.
The Command extension enables the execution of Multi-Line Commands from Terminal prompt.
Terminal Multi-Line Input with Edit, Insert, Delete, Print extension for IRIS and Caché
IRIS and Caché have just single command lines in terminal available
This Multi-Line Commands Editor also will execute the Multi-line Commands.
In addition, it is independent of access to %SYS and can be installed in any namespace
Special thanks to @Jeffrey Drumm who inspired me to this and supported me as beta-tester.
The Command extension enables the execution of Multi-Line Commands from Terminal prompt.
Installation & Execution
Import %ZML.xml to Namespace %SYS
Optionally you may add this line to your %ZLANGC00.mac for a simplified use:
ZML do ^%zml quit ; add multi line command in terminal
and
USER>zmlotherwise, just call it from the terminal command prompt
USER>do ^%zml
Usage
at the prompt USER:zml:1>
- enter commands as usual
- trigger execution by an empty line
- stop multi-line option with a single '.' (dot) at first position
Example
USER>zml
Entering multi line mode. Run with empty line.In Cache for Windows (x86-64) 2018.1.3 (Build 414U) I found something very useful
Allow limited durability for demo and development IRIS-Docker-micro-Durability During development of a container based demo I found the need to access a fresh docker
an instance of IRIS image (e.g intersystems/iris-community:2020.2.0.199.0) over and over.
To bypass loading my code repeatedly, I developed this workaround.
Docker support
The principle of a persistent IRIS database outside the container is unchanged.
But now the whole setup is moved into Dockerfile and docker-compose.yml
Prerequisites
Make sure you have git and Docker desktop installed.
Using the IRIS native API for Node.JS was the opportunity to present
a MicroService operating in a Docker container.
A demo video is now also available to watch the demo in operation.
Instead of a utility you call directly on your IRIS host you now send a work-packages
to the MicroService as would typically do with System Interoperability (aka.ENSEMBLE):
of course, you have the option of more than one WebSocket Server.
Once the WebSocket Client Service has done its job you get back the result from it.
While the classic solution followed rather close the concepts and design of the ancestors
Caché / IRIS allows a more modern approach to flexible/multidimensional properties