#Tips & Tricks

12 Followers · 335 Posts

Pieces of experience in InterSystems Technology which solve some particular problem in elegant or unusual way.

Article Colin Langella · Mar 11, 2025 2m read

Intro

In the process of trying to get more familiar with Objectscript I decided to try to build a general priority queue since I wasn't able to find an implementation anywhere. My though process for implementing this followed this general path.

Binary Heap

My first though to try to make this work quickly was to implement a binary heap and my first attempt at this used a multidimensional to build it. This version was relatively efficient, worked for strings/numbers natively, and worked for objects be letting the user override the comparitor.

Class pqueue.Queue Extends %RegisteredObject
{

Property Data As %Any [ MultiDimensional ];

Property Size As %Integer [ InitialExpression = 0 ];

Property Comparitor As %String [ InitialExpression = "(a,b) return a < b" ];
    
    Method Swap(i As %Integer, j As %Integer) As %Status [ Private ]
    {
    set temp = ..Data(i)
    set ..Data(i) = ..Data(j)
    set ..Data(j) = temp
    }
    
    Method Comp(x As %Any, y As %Any) As %Boolean [ Private ]
    {
    return $XECUTE(..Comparitor, x, y)
    }
    
    Method PercolateUp(idx As %Integer) [ Private ]
    {
    while idx > 0 {
    set newidx = (idx-1)\2

    if ..Comp( ..Data(idx), ..Data(newidx) ) do ..Swap( idx, newidx )
    else                                     Quit

    set idx = newidx
}
}

Method PercolateDown() [ Private ]
{
set idx = 0

while ((idx+1)*2) < ..Size {
        if ..Comp( ..Data(idx*2+2), ..Data(idx*2+1) ) set newidx = idx*2+2
        else                                          set newidx = idx*2+1
    
        if ..Comp( ..Data(idx), ..Data(newidx) ) Quit
    
        do ..Swap( idx, newidx )
        set idx = newidx
    }
    
    if ( (idx*2+1 < ..Size) && ..Comp( ..Data(idx*2+1), ..Data(idx) ) ) do ..Swap( idx, idx*2+1 )
    }
    
    Method IsEmpty() As %Boolean
    {
    return ..Size = 0
    }
    
    Method Top() As %Any
    {
    if ..IsEmpty() return ""
    return ..Data(0)
    }
    
    Method Put(inp As %Any) As %Status
    {
    set sts = $$$OK
    
    set ..Data( ..Size ) = inp
    do ..PercolateUp( ..Size )
    set ..Size = ..Size + 1
    
    return sts
    }
    
    Method Get(Output obj As %Any) As %Status
    {
    set sts = $$$OK
    if ..IsEmpty() {
        set obj = ""
        return $$$ERROR( "Cannot Get() from empty Queue" )
    }
    
    set obj = ..Data( 0 )
    set ..Size = ..Size - 1
    set ..Data( 0 ) = ..Data( ..Size )
    do ..PercolateDown()
    kill ..Data( ..Size )
    return sts
    }
    
    Method GenerateComparitor(operator As %String = "<", transform As %String = "") As %Status
    {
    set ..Comparitor = "(a,b) return a" _ transform _ " " _ operator _ " b" _ transform
    return $$$OK
    }
    
    }

After getting this working I wanted to try out different internal arrays since I assumed multidimensional arrays must be slower than a simple integer indexed array. So I modified the above code to use

*   `Property Data As list Of %Any;` : This works OK but it is about 3-4 times slower than using a multidimensional making it pointless.
*   `Property Data As %DynamicArray;` : I assumed this would be relatively fast but proved to be slow to the point of absurdity. When the amount of data stored in the queue is small it is around as fast as the `list of %Any`, but as the data grows the time it takes to make inserts and gets grows linearly which makes it pointless to build a heap on top of.

## Using the Multidimensional Array's Self-sorting

On its face this idea seems pretty simple, use the fact that the multidimensional array is always sorted to grab the lowest cost (highest priority) item. A problem with this are that indexing by an object simply uses the string representation of that object which isn't useful. To handle this a customer `evaluator` function is needed to return the integer or string evaluation of an object which is then sorted, it is then stored as `data( evaluation, obj_str_rep ) = object` which ensures that objects are correctly sorted even when two objects evaluate to the same value.

    Class pqueue.SparseQueue Extends %RegisteredObject
    {
    
    // Parameter Comp(a,b) As $XECUTE(..Comparitor, a, b);
    
    Property Data As %Any [ MultiDimensional ];
    
    Property Size As %Integer [ InitialExpression = 0 ];
    
    Property Evaluator As %String [ InitialExpression = "(a) return a" ];
    
    Method IsEmpty() As %Boolean
    {
        return ..Size = 0
    }
    
    Method Top() As %Any
    {
        if ..IsEmpty() return ""
        return $Order( ..Data("") )
    }
    
    Method Put(inp As %Any) As %Status
    {
        set sts = $$$OK
    
        set ..Data( $XECUTE(..Evaluator, inp), inp ) = inp
        set ..Size = ..Size + 1
    
        return sts
    }
    
    Method Get(Output obj As %Any) As %Status
    {
        set sts = $$$OK
        if ..IsEmpty() {
            set obj = ""
            return $$$ERROR( "Cannot Get() from empty Queue" )
        }
    
        set loc = $ORDER( ..Data("") )
        set obj = ..Data(loc, $ORDER( ..Data(loc, "")))
    
        set ..Size = ..Size - 1
        kill ..Data( loc, obj )
        return sts
    }
    
    Method GenerateEvaluator(transform As %String = "") As %Status
    {
        set ..Evaluator = "(a) return a" _ transform
        return $$$OK
    }
    
    }

This method proved to be by far the fastest. It has some slight disadvantages in that it can be harder to write an evaluator than a comparitor and, in the form given above, it cannot hold the same object at the same value twice (this is a rare case but could theoretically be a problem or a benefit).

## Speed Test

To test these out I wrote a simple script that generates a large randomized weighted directed graph and runs [Dijkstra's shortest path algorithm](https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/) using a given queue object. Using a graph with `150000` vertices where each has `10` neighbors, the output is printed below. Here while the algorithm is running an update is printed every `10000` edges checked, where the time since the last 10 thousand and size of the priority queue is printed, with some final stats at the end. The order they are run in is

*   Self-sorting Multidimensional

*   Heap Multidimensional

*   Heap Dynamic Array

*   Heap List of Object

> Generated Random Graph
0
0 261
Question Colin Brough · Feb 25, 2025

We have some ObjectScript code in a custom business process:

When Log Trace Events is ticked on the business process in the Production view in the management portal, the argument is obviously computed.

Our question is whether the argument is computed when Log Trace Events is not ticked? Don't want to accidentally include something in a $$$TRACE() statement that takes enough computation to make a performance difference when released to production, even though the final output is not written to the event log.

3
0 175
Article Sergio Farago · Feb 21, 2025 3m read

Hello Community:

Let's go with the last article on how to record yourselves for the Article Contest video bonus.

I'm not going to go into how to do very specific things in editing because it varies depending on the program you use. The keyboard shortcuts and menus are different, but the concept is the same. You are going to use a programme to organise the recorded material, remove the excess and give it structure. Many of these softwares are free (Capcut, Canva and if I'm not mistaken DaVinci had a free version). I've been editing with Adobe Premiere for almost ten years now (wow, I'm getting old), so if you have any questions about this software, feel free to write to me.

Here are some concrete tips:

0
0 124
Article Sergio Farago · Feb 18, 2025 4m read

Hello Community:

Do you want to know how to record yourself without looking like you're speaking from a cave? Are you one of those who say you ‘don't come off well on camera’? 

Today I'm going to share with you some specific tips that I learned after several years of filming interviews for television and networks. I remind you that these are tips in case you are thinking of taking advantage of the Article Contest video bonus. However, they are tips that I'm sure you can use for presenting webinars, video calls and filming yourself in general.

0
0 138
Article Sergio Farago · Feb 14, 2025 3m read

Hi Community,

As you may know, this year's Spanish Technical Articles contest will be in May. I am going to make a series of articles to support you in the creation of your articles, giving tips and tricks. Perhaps they will be useful for the contest you have active in this community as well.

As you may know, one of the bonuses or extra points you can receive is to add a video tutorial to your article. You may not even know how to approach this issue, no problem! I'm here to give you some tips that you can apply not only to the creation of these videos, but to any other.

2
1 180
Article Murray Oldfield · Jan 12, 2017 19m read

Hi, this post was initially written for Caché. In June 2023, I finally updated it for IRIS. If you are revisiting the post since then, the only real change is substituting Caché for IRIS! I also updated the links for IRIS documentation and fixed a few typos and grammatical errors. Enjoy :)


In this post, I show strategies for backing up InterSystems IRIS using External Backup with examples of integrating with snapshot-based solutions. Most solutions I see today are deployed on Linux on VMware, so a lot of the post shows how solutions integrate VMware snapshot technology as examples.

29
10 12304
Article Megumi Kakechi · Nov 7, 2024 1m read

InterSystems FAQ rubric

It can be obtained with a List query of the %SYS.Namespace class.

1. Create a routine like this:

getnsp
   set##class

2. Run it in your terminal

USER>do ^getnsp
%SYS
DOCBOOK
SAMPLES
USER

The method of executing class queries introduced in this article can be applied in a variety of cases.

You can see various class queries in the class reference. For example,
 %SYS.DatabaseQuery: GetFreeSpace() Free space in database
 %SYS.GlobalQuery: DirectoryList            List of global names in database
 %SYS.GlobalQuery: Size

4
1 639
Article David Hockenbroch · Nov 5, 2024 7m read

As we keep updating our software, we often realize that we require more and more modern solutions. So far, only one major piece of our software relies on reading barcodes in documents and images. Since Cache did not have a means of reading barcodes in the past, we have always achieved our goals by using a Visual Basic 6 application. However, it is no longer an ideal solution because it is currently complicated to maintain it. IRIS also lacks this capability, but it has recently got an option that makes up for it: embedded Python!

2
1 620
Article Megumi Kakechi · Nov 14, 2024 1m read

InterSystems FAQ rubric

By default, the order of columns in a table is determined automatically by the system. To change the order, explicitly set the order for each property using the property keyword SqlColumnNumber when defining the class.

Example:

Property Name As %String [SqlColumnNumber = 2];

Please see the documentation below.

SqlColumnNumber

If you want to change the SQL table name, specify SqlTableName. If you want to change the column name (field name), specify SqlFieldName.

Both apply only to persistent classes.

0
0 237
Article Kate Lau · Oct 28, 2024 8m read

I am just writing something to share what I encountered last night, which is the IRIS 2024.3 does not comes with Python by default any more!!!

Which means that I need to install it by myself!!😅 The pros is, I can select my python version😁🤭💃 The trouble is.... at the first place.... I don't know what I should do😥. By going through the community (I am much more prefer than the official document, sorry InterSystems document team😓 ), I found the following piece 

https://docs.intersystems.com/iris20242/csp/docbook/DocBook.UI.

0
0 395
Article Anthony Master · Oct 17, 2024 2m read

I was working on a DTL but kept getting ERROR #5002... MAXSTRING errors. The problem was that most of the DTL GUI action steps only support the string data type when working with the segments. A %String has a limit of 3,641,144 characters and my OBX5.1 was 5,242,952 characters long as the example provided. Of course PACS admin stated ultra high quality up to and including 4K resolution files were needed, so we could not get the vendor to compress or reformat these files to compressed jpg or something similar.

Initially this vendor sends a 2.3 ORU^R01

7
1 530
Article David Hockenbroch · Oct 14, 2024 9m read

Many programming languages use the try-and-catch construct to handle runtime errors gracefully. If the code within the try block encounters an error, it will throw an exception to the catch block, where the error handling occurs. Today we will dive into the ObjectScript implementation of this construct and discuss some ways to clean things up.

1
3 478
Article Nicole Sun · Mar 25, 2024 7m read

In the business world, every second counts, and having high-performing applications is essential for streamlining our business processes. We understand the significance of crafting efficient algorithms, measurable through the big O notation.

Nevertheless, there are numerous strategies to boost the performance of systems built on the IRIS Data Platform. These strategies are equally crucial for optimizing overall efficiency.

Let's join the journey for a sneak peek into the tips for making IRIS Data Platform work better, where every little trick will help your applications shine.

1.

10
4 707
Article Chi Nguyen-Rettig · Sep 21, 2024 3m read

There are many applications for working with HL7 V2 messages, but the tools for working with XML in IRIS Management Portal and Cache Studio are limited. While plenty of external utilities and IDEs work with XML messages and even C-CDA documents, there is a compelling case for being able to test directly against the IRIS C-CDA framework. 

Testing within the IRIS environment provides the necessary context: 

  • XML parser configuration
  • XML namespace context
  • Facility and OID setup
  • IHE header handling
  • The HS.IHE.Util, HS.Util.XSLTTransformer, and %XML.XSLT.
7
4 487
Question Colin Brough · Sep 27, 2024

We are doing healthcare interface development.

Developers have Ensemble installed locally on their laptops - code will be developed locally then deployed to integration, test/UAT and ultimately production servers in due course.

One of the other applications we are developing around happens to utilise an Iris desktop client to a remote Iris server. We want to have the application available on the developers laptops alongside the local Ensemble instance.

✅ It appears that if we install their desktop client then install our local Ensemble server, things work.

3
0 170
Article Katherine Reid · Jul 16, 2019 1m read

There's an easy new way to add certificate authority (CA) certificates to your SSL/TLS configurations on InterSystems IRIS 2019.1 (and 2018.1.2) on Windows and Mac.  You can ask IRIS to use the operating system's certificate store by entering:

%OSCertificateStore

in the field for "File containing Trusted Certificate Authority X.509 certificate(s)".   Here's an image of how to do this in the portal:

And here's a link to the documentation which describes this.  It's in the list of options under "File containing trusted Certificate Authority certificate(s)".

That's all you need to do!

5
4 1933
Question Colin Brough · Aug 30, 2024

I can START and STOP a business process via its Schedule setting.

Is it possible to change the value of another Setting in an analogous way?

I can imagine a SettingSchedule that could look like 

action:YYYY-MM-DDThh:mm:ss[,action:YYYY-MM-DDThh:mm:ss]

But rather than just START or STOP, action could be "SET Setting = value", overriding whatever the normal value is.

Is there an existing way of achieving this kind of functionality?

I've got a business process that triggers from a scheduled task, and sends documents to a downstream system according to business requirements.

4
0 191
Announcement Raj Singh · Feb 14, 2023

For those of you who still use the Studio IDE for ObjectScript programming and are going through the process of migrating to VS Code, did you know there's a section in the VS Code documentation just for you? Have a look at the Migrating from Studio chapter. It covers:

  • Server-side editing and source control
  • Studio projects
  • Importing server definitions from the Windows Registry
  • Loading Studio snippets and syntax colors

And now there's a new section, Keyboard Shortcuts, that shows you the VS Code equivalent for shortcuts you may be used to, so your hands never have to leave the keyboard.

6
0 561
Article Hiroshi Sato · Aug 22, 2024 1m read

InterSystems FAQ rubric

The following code downloads https://www.intersystems.com/assets/intersystems-logo.png and saves the file as c:\temp\test.png.

You need to define an SSL configuration called SSLTEST before executing this code

ClassMethodAs%Status
0
3 248
Article Megumi Kakechi · Aug 15, 2024 3m read

InterSystems FAQ rubric

Temporary globals stored in the IRISTEMP/CACHETEMP databases are used when a process does not need to store data indefinitely, but requires the powerful performance of globals. The IRISTEMP/CACHETEMP databases are not journaled, so using temporary globals does not create journal files.

The system uses the IRISTEMP/CACHETEMP databases for temporary storage and are available to users for the same.

For more information about temporary globals and the IRISTEMP database, see the following document:
Temporary Globals and the IRISTEMP Database

The globals used as temporary are:

1. System temporary globals (^IRIS.Temp*, ^%cspSession, ^CacheTemp*, ^mtemp*, etc.)
2. Temporary globals mapped to IRISTEMP/CACHETEMP by the user
3. 

0
6 487
Article Tomoko Furuzono · Aug 8, 2024 2m read

InterSystems FAQ rubric

If you do not specify the option to remove the mirror attribute of the mirror database when deleting the mirror configuration, the database cannot be restored to a normal state and will be mounted read-only the next time it is mounted. To restore the database to a read-write state, you must remove the mirror attribute using the system routine ^MIRROR.

0
2 413
Article Zeljko Sucic · Jul 26, 2024 7m read

As a part of the IRIS Python 2024 contest, my colleague Damir and I went with an idea to build a platform called ShelterShare for connecting victims and volunteers for shelter requests . To do so we chose django as a framework and proceeded to build the first version with 3 different docker containers, django, iris and nginx which would then utilize IRIS as a pure Database engine via the beautifly composed django_iris (cudos to Dimitry). As we were progressing fast, we decided to explore the option of running it within the same container as IRIS by utilizing WSGI added in 2024.1.

5
1 331
Article Hiroshi Sato · Mar 28, 2024 1m read

InterSystems FAQ rubric

Here, we will introduce a sample code for registering and referencing task schedules.

 ①Sample of task schedule registration

*Create a task to execute do ^TEST every day at 1:00 am. 

 set task=##class(%SYS.Task).%New()
 set task.Name="MyTask1"
 set taskDescription="Execute ^xxx every day at 1:00 AM" // Optional
 set task.NameSpace="USER"
 set task.TimePeriod=0
 set task.DailyFrequency=0
 set task.DailyFrequencyTime=""
 set task.DailyIncrement=""
 set task.DailyStartTime=$ZTimeh("01:00:00")
 set task.DailyEndTime=""
 set task.TaskClass="%SYS.Task.RunLegacyTask"
 set task.
2
0 352