Vitaliy Serdtsev · Nov 26, 2025 go to post

I agree.

$CASE(1,
%source.userActionone:"User action one"%source.userActiontwo:"User action two",
%source.userActionthree:"User action three",
%source.userActionfour:"User action four"%source.userActionfive:"User action five"%source.userActionsix:"User action six"%source.userActionseven:"User action seven"%source.userActioneigth:"User action eigth"%source.userActionnine:"User action nine"%source.userActionten:"User action ten"%source.userActioneleven:"User action eleven"%source.userActiontwelve:"User action twelve"%source.userActionthirteen:"User action thirteen",
%source.userActionfourteen:"User action fourteen", :"Other")

But the result will still be only one value, even if all %source.userActionXXX=1.

Vitaliy Serdtsev · Nov 26, 2025 go to post

What result should $select return if the conditions %source.userActionone=1 AND %source.userActiontwo=1 are true ?

Vitaliy Serdtsev · Nov 24, 2025 go to post

Strange. I just checked on Caché Studio 2014.1.5 and Caché 2014.1.5 (logged in under superuser) - output

CSTUDIO.EXE

 

Vitaliy Serdtsev · Nov 20, 2025 go to post

json=[
{"s":"iPhone1"},
{"s":"iPhone2"},
{"s":"IPHONE3"},
{"s":"IPHONE4"},
{"s":"Phone5"}
]

##class(%ASQ.SetUtils).pp(json.apply("$[*]?(@.s like_regex '\p{LL}\w+')"))

Output (IRIS 2025.3CE):
[
{
"s": "iPhone1"
},
{
"s": "iPhone2"
}
]

Vitaliy Serdtsev · Nov 20, 2025 go to post

Check the result outputs of the following code from Studio and from Terminal:

w $zu(67,13,$j)
Vitaliy Serdtsev · Nov 13, 2025 go to post

A long time ago, back in the days of Caché, I made a series of articles on creating a web application based on REST and CSP with my own static file processing. Try it, maybe you can use something from there.

Vitaliy Serdtsev · Nov 13, 2025 go to post

I will assume that you are using "Normal" (in which the user _SYSTEM is turned off) or even "Locked Down" (the user "UnknownUser" has no roles at all): Initial User Security SettingsDOC

I'm using "Locked Down", IRIS 2025.2CE and ran into a lot of different bugs when using WebTerminal v4.9.5:

  • <PROTECT>endSession+25^%SYS.cspServer
  • <LICENSE LIMIT EXCEEDED>
  • etc.
Fortunately, the WebTerminal source code is available for analysis and editing.

The problem can be solved in two ways: either fix the source code or add the missing role. I chose the latter.

In my case, it is enough for the web application /terminalsocket to add the %Admin_Secure role in addition to the existing roles. After that, it doesn't hurt to clean up all existing sessions:

kill ^WebTerminal("AuthUser")
If the <LICENSE LIMIT EXCEEDED> error persists after this, restart the IRIS instance.

PS: Advisory for IRISSECURITY in InterSystems IRIS 2025.2

Vitaliy Serdtsev · Nov 13, 2025 go to post

Credentials are not requested, as most likely your existing session has not expired yet. By default, the timeout is 1 hour (see the "WebTerminal.Engine:WSKEYEXPIRES" class parameter).

Vitaliy Serdtsev · Nov 5, 2025 go to post

I would venture to assume that this difference is due to the overhead of calling the class method. In other words:

  • ##class(%DynamicArray).%New() -> ..%OnNew() -> $ZU()
  • [] -> $ZU()
There was a similar topic: Shared code execution speed

Vitaliy Serdtsev · Oct 31, 2025 go to post

"Real life" *.inc entry is to execute macro routine "Entry^HS.Local.VA.Util.Log(%arr,,"D")" if Global ^GlFSL("Debug") is >0 by calling from a classmethod as $$$TestIf(arr) - no return value is required.
#define TestIf(%arr) if (^GlFSL("Debug")>0) {do Entry^HS.Local.VA.Util.Log(%arr,,"D")}
;or
#define TestIf(%arr) do:^GlFSL("Debug")>0 Entry^HS.Local.VA.Util.Log(%arr,,"D")
Usage:
$$$TestIf(5)

Vitaliy Serdtsev · Oct 31, 2025 go to post

Statement "set a = $$$TestIf(3)" is included into a classmethod with no other code in. Expected output 5
What is the expected result for the next operator?
set $$$TestIf(-3)

Vitaliy Serdtsev · Oct 30, 2025 go to post

You have two mistakes.

  • Instead
    for {i=1:1:%count set x=
    should be
    for i=1:1:%count {set x=
  • Macros ≠ Function

A working example:

  #define MyLoop(%count,%result) set ref="",%result="" for i=1:1:%count set ref=$order(^%SYS("JOURNAL",ref),-1),%result=%result_$listbuild(ref)

  $$$MyLoop(5,x)   write $listtostring(x)

Vitaliy Serdtsev · Oct 30, 2025 go to post

Example of @Robert Cemper compiles without errors for me (even on Caché 2018.xxx):

Class dc.a Abstract ]
{

ClassMethod Test() {   #define MyLoop(%count) set x="" for i=1:1:%count set x=$order(^%SYS("JOURNAL",x),-1) write x,!    $$$MyLoop(5) }

}

Vitaliy Serdtsev · Oct 30, 2025 go to post

If the array is multidimensional, then you can't do without loops (the code is without error handling):

  #define ArrayToStr(%arr,%str) set ref=$name(%arr),%str="s " for  {set ref=$query(@ref,1,val) quit:ref=""  set %str=%str_$$FormatName^%qcr(ref,1)"="##class(%Utility).FormatString(val)_","} set $extract(%str,*)=""
  #define StrToArray(%str) xecute %str

Usage:

  set a(0)=7
  set a(1,"color")="green"
  set a(1,"color","green")=""
  set a("color",$listbuild($double(3)))=$listbuild("red","blue")

  $$$ArrayToStr(a,str)   zwrite str   kill a   $$$StrToArray(str)   zwrite a

Vitaliy Serdtsev · Oct 30, 2025 go to post

I would like to have *inc file entry to convert an array into a string and string into an array.
If the array is one-dimensional, then you can do without cycles altogether. I'll give you a small example below:

  #define Array1ToJSONString(%arr,%json)##continue
  s ##unique(new)=##class(%ZEN.proxyObject).%New()##continue
  d ##unique(old).%CopyFromArray(.%arr),##continue
    ##class(%ZEN.Auxiliary.altJSONProvider).%WriteJSONStreamFromObject(.%json,##unique(old))##continue
  s %json=%json.Read(3641144)
  
  #define JSONStringToArray1(%json,%arr)##continue
  d ##class(%ZEN.Auxiliary.altJSONProvider).%ConvertJSONToObject(%json,,.##unique(new)),##continue
    ##unique(old).%CopyToArray(.%arr)

Usage:

  set a("color")=$listbuild("red","blue")
  set a("price")="expensive"
  set a("size")=$listbuild("large","small")
    
  $$$Array1ToJSONString(a,jsonStr)
  zwrite jsonStr
  $$$JSONStringToArray1(jsonStr,b)
  zwrite b

Vitaliy Serdtsev · Oct 29, 2025 go to post

Attention: You can INCLUDE just 1 single *.INC in a class definition.
Including Include Files

To include multiple include files at the beginning of a class definition, the syntax is of the form:

Include (MyMacros, YourMacros)

Vitaliy Serdtsev · Aug 21, 2025 go to post

import iris

# first, we connect to the %SYS namespace conn = iris.connect('localhost:1972/%SYS','_SYSTEM',pwd,10,True) irispy = iris.createIRIS(conn)

# here we switch to the USER namespace newNameSpace = irispy.classMethodString('%SYSTEM.Process','SetNamespace','USER')

# now we can call the method from the new namespace #print(irispy.classMethodInteger('DC.Unix','RoundPosixToSeconds',1154669852181849976))

conn.close()

Vitaliy Serdtsev · Aug 15, 2025 go to post
#Include %sqlx
set newposix $$$sqlxPosixTimeEncode(+$p($$$sqlxPosixTimeDecode(posix),".",1))

Сheck:

for posix = 1154669852181849976, -6979664624441081856, 1406323805406846975 {

  set newposix $$$sqlxPosixTimeEncode(+$p($$$sqlxPosixTimeDecode(posix),".",1))

  write ##class(%PosixTime).LogicalToTimeStamp(posix),!,
        ##class(%PosixTime).LogicalToTimeStamp(newposix),!!
}

2025-05-27 12:06:15.003
2025-05-27 12:06:15
 
0001-01-01 00:00:00
0001-01-01 00:00:00
 
9999-12-31 23:59:59.999999
9999-12-31 23:59:59
Vitaliy Serdtsev · Aug 11, 2025 go to post
 

source code of dc.observation_lab

Class dc.a Extends %Persistent SqlTableName observation_lab ]
{

Index iCode On code;

Index iCodeText On codetext;

Property code As %String(MAXLEN 2000);

Property codetext As %String(MAXLEN 2000) [ SqlFieldName code_1_text ];

/// d ##class(dc.a).Test()
ClassMethod Test(= {5e6})
{
  t=$zh
  d DISABLE^%NOJRN
  ^dc.aD,^dc.aI
  i=1:1:c=i-1#1000+1,^dc.aD(i)=$lb("",c,"code_1_text_"_c)
  ^dc.aD=N
  ENABLE^%NOJRN
  "(time) insert = ",$zh-t,!
  
  t=$zh
  d ..%BuildIndices(,,,$$$NO)
  "(time) %BuildIndices = ",$zh-t,!
  
  t=$zh
  d $system.SQL.TuneTable("dc.observation_lab",,1,,,,,,,"100%")
  ;&sql(TUNE TABLE dc.observation_lab %SAMPLE_PERCENT '100%')
  "(time) tune table = ",$zh-t,!
}

}

The following query does not use iCode/iCodeText indexes (2025.2.CE):

select code_1_textcount(code_1_text)
  from dc.observation_lab
  group by code_1_text
  order by desc

PS: if possible, I would try to convert the text into a number in some way and index this number already, perhaps even with the bitmap type.

Vitaliy Serdtsev · Aug 4, 2025 go to post

I completely agree with you.👍

I hope someone from InterSystems will pay attention to your post.

PS: and in addition, it would also be nice to solve the issue with %FromOref(): either the code or the documentation needs to be fixed. On version 2025.2.CE it still doesn't work.

Vitaliy Serdtsev · Aug 4, 2025 go to post

Here explained to us that this is not a bug, but a feature: <PROTECT> *Function not allowed in IRIS Native python

Starting from 2024.1 IRIS Native disallows routine invocations. Please use class methods instead.

For reference, these changes can be identified as DP-422635 and DP-424156.

PS: and yes, additional roles and resources like %Native_*/%All etc. no eliminate the <PROTECT> error. Checked on version 2025.2.CE

Vitaliy Serdtsev · Jul 16, 2025 go to post

Very strange syntax:

But if we tried at once with a single statment with a select into (1 value) it fails
INSERT INTO Sample.YoungPeople (PASReligionCodevalues (SELECT internalPatientNumber FROM
Pennine_TIE_Clinicom_Link.PMISPECIALREGNCA where InternalPatientNumber=100)

See: