Article Eduard Lebedyuk · Jun 18, 2020 1m read

Often we need to debug a Business Operation. Tracing and logging work but sometimes you want to work with a BO as with your local terminal session.

Here's how you can do that on any operating system.

Windows has a great tool for debugging Business Operations - Foreground mode. In that mode Windows launches a local terminal with operation job.

Note that there's  an issue with some InterSystems IRIS versions (older than 2021.1) which caused cterm launch instead of iristerm. To fix that you can either install Caché/Ensemble/HealthShare on a same server or run this reg file:

0
2 607
Announcement Eduard Lebedyuk · Apr 10, 2020

I'm happy to announce the release of the interface to Julia programming language for InterSystems IRIS. Execute Julia code and more from InterSystems IRIS. This project brings you the power of Julia right into your InterSystems IRIS environment:

  • Execute arbitrary Julia code
  • Seamlessly transfer data from InterSystems IRIS into Julia
  • Build intelligent Interoperability business processes with Julia Interoperability Adapter
  • Experiment in Julia Shell, right inside your InterSystems IRIS terminal
0
0 299
Question Eduard Lebedyuk · Apr 1, 2020

During runtime I build an object which is essentially a wrapper over in-memory table:

col1 ... colN
val11 ... valN1
val12 ... valN2

I want to use this object as a part of INSERT or UPDATE queries, based on a value of some column (the main use case one of the columns is an ID value)

What's the best way to expose the object to SQL?

I have complete control over object class, so if I need  to add something (or even change runtime internals), it's no problem.

Object may have different columns depending on runtime situation, but during one query execution the fields are constant.

13
0 750
Question Eduard Lebedyuk · Mar 17, 2020

I have a C string and I need to build a $lb from it.

This code works fine for strings shorter than 254 characters:

char *str = "some string";
int len = strlen(str);
int add = 2;
char *list = malloc(len + add + 1);
char lenChar = len + add;
sprintf(list, "%c\x01%s", lenChar, str);

Thought maybe someone can share the code for longer strings?

1
1 369
Question Eduard Lebedyuk · Mar 6, 2020

Simple problem:

  1. I leave a long-running command in terminal
  2. Switch to another task(s)
  3. Remember that I need to check on my command after a few hours

Is there any way to force terminal to the foreground after current command ends?

This is Windows with cterm/iristerm although Putty/Kitty solution would also be nice.

6
0 667
Article Eduard Lebedyuk · Feb 11, 2020 6m read

Asymmetric cryptography is a cryptographic system that uses pairs of keys: public keys which may be disseminated widely, and private keys which are known only to the owner. The generation of such keys depends on cryptographic algorithms based on mathematical problems to produce one-way functions. Effective security only requires keeping the private key private; the public key can be openly distributed without compromising security.

In such a system, any person can encrypt a message using the receiver's public key, but that encrypted message can only be decrypted with the receiver's private key.

2
0 819
Article Eduard Lebedyuk · Jan 16, 2020 2m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

0
0 697
Question Eduard Lebedyuk · Jan 15, 2020

How do I rename class programmatically?

This discussion touches on data move which, is not a concern in my case (BPL renames).

I also don't care about external references.

The best I got is:

  1. Get class text as string
  2. Replace class name in this string
  3. Save new string as new class
  4. Open new class as object
  5. Delete storage
  6. Compile class

Are there any better alternatives?

Also found this discussion.

5
1 606
Question Eduard Lebedyuk · Jan 15, 2020

I need to know if given package exists or not.

Currently found two solution - one doesn't work, another works but I don't like it.

Solution 1.

I started, of course, with %Dictionary package - it has PackageDefinition class after all.

However, %ExistsId returned 0 on packages that clearly do exist, so I went to %LoadData, it uses this macro to determine if the package exist:

#define PACKAGE(%package)             ^oddPKG($zcvt(%package,"u"))

And zw ^oddPKG showed the root cause - ^oddPKG global only contains data for packages with tables (or something along these lines).

Solution 2.

12
0 574
Question Eduard Lebedyuk · Jan 14, 2020

Is there a way to get dynamic object from iterator?

set arr=[1,2,3]
set iter=arr.%GetIterator()

I pass iterator several frames down and I'd rather avoid passing both the array and iterator, but for debugging I need to access original object in a situation where only iterator is available.

Is there a way to do it?

5
0 543
Article Eduard Lebedyuk · Jan 13, 2020 1m read

While and for are pretty similar, but sometimes you need to do a not recommended thing - change cycle boundaries.

In this situation while and for are different. For calculates boundaries once per run and while calculates boundaries on every iteration.

Consider this code sample:

set x = 5
for i=1:1:x {
     write "i: ", i,", x: ", x,!
     set x = x+1
}

You'll get this output:

i: 1, x: 5
i: 2, x: 6
i: 3, x: 7
i: 4, x: 8
i: 5, x: 9

Compare to while cycle:

set i = 1
set x = 5
while (i<=x) {
    write "i: ", i,", x: ", x,!
    set x = x+1
    set i = i+1
}

The output is infinite:

7
0 491
Article Eduard Lebedyuk · Jan 6, 2020 1m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

0
0 474
Article Eduard Lebedyuk · Dec 17, 2019 3m read

This series of articles would cover Python Gateway for InterSystems Data Platforms. Execute Python code and more from InterSystems IRIS. This project brings you the power of Python right into your InterSystems IRIS environment:

  • Execute arbitrary Python code
  • Seamlessly transfer data from InterSystems IRIS into Python
  • Build intelligent Interoperability business processes with Python Interoperability Adapter
  • Save, examine, modify and restore Python context from InterSystems IRIS

Other articles

The plan for the series so far (subject to change).

0
0 537
Article Eduard Lebedyuk · Dec 9, 2019 1m read

If you work with anything other than English, you would earlier or later encounter the characters from the title or just plain ??????????.

Encodings are usually known, but sometimes you just get gibberish and need to make sense of it.

In this cases $zcvt is your friend, the three argument form specifically.

But there are a lot of options. So here's an utility script to check how the text would look like in different encodings:

4
0 446
Article Eduard Lebedyuk · Dec 7, 2019 1m read

%objlasterror is a useful reference to the last error.

Every time $$$ERROR is called, %objlasterror is set to a result of this call.

It's important in cases where you want to convert exception to status:

Try {
   //  quality code
} Catch ex {
   Set sc = $g(%objlasterror, $$$OK)
   Set sc = $$$ADDSC(sc, ex.AsStatus())
}

Because AsStatus calls $$$ERROR under the wraps, the order is important, first you need to get %objlasterror and  convert exception after that.

8
3 1420
Article Eduard Lebedyuk · Dec 3, 2019 1m read

One of the most useful features in Studio is code snippets.

Here's how to add snippets to VSCode.

Here's a generalized instructions.

1. Go to File - Preferences - User Snippets and choose objectscript.

2. Add your snippet, here's an example:

"SQL Statement": {
    "prefix": ["sql"],
    "body": ["#dim rs As %SQL.ISelectResult",
            "set rs = ##class(%SQL.Statement).%ExecDirect(,\"SELECT * FROM\")",
            "while rs.%Next() {",
            "\twrite rs.ID, !",
            "}"]
}

In here:

  • prefix - what you need to type for the snippet to appear
  • body - snippet body
1
5 785
Article Eduard Lebedyuk · Nov 22, 2019 1m read

This quick guide shows how to serve HTTPS requests with InterSystems API Management. Advantage here is that you have your certs on one separated server and you don't need to configure each backend web-server separately.

Here's how:

1. Buy the domain name.

2. Adjust DNS records from your domain to the IAM IP address.

3. Generate HTTPS certificate and private key. I use Let's Encrypt - it's free.

4. Start IAM if you didn't already.

5. Send this request to IAM:

2
1 642
Article Eduard Lebedyuk · Nov 20, 2019 9m read

In this article, I would like to talk about the spec-first approach to REST API development.

While traditional code-first REST API development goes like this:

  • Writing code
  • REST-enabling it
  • Documenting it (as a REST API)

Spec-first follows the same steps but reverse. We start with a spec, also doubling as documentation, generate a boilerplate REST app from that and finally write some business logic.

This is advantageous because:

6
10 3439
Question Eduard Lebedyuk · Nov 14, 2019

I have several Business Services which I need to run once on each trigger.

Trigger can be either:

  • Specific time (so once a day, every day)
  • Specific day (so once a month, every month)

For the time, it would be stable (i.e. 0100), but the second case varies - one month it could be 10th, another month - 12th.

After each run I want the service to turn off, so that all the time the service is not running it would be colored grey in Production Management Page.

I plan to use Task Scheduler,but open to suggestions.

Thoughts? Ideas? Code?

2
0 453