Vitaliy Serdtsev · Jun 11, 2025 go to post

See Query Parameters

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
  <page xmlns="http://www.intersystems.com/zen">
    <multiSelectSet
      sql="select 'Apple' union select 'Banana' union select 'Cherry'"
    />
  </page>
}
Vitaliy Serdtsev · Jun 9, 2025 go to post

Let's suppose two different routines use one and the same chunk of code. From the object-oriented POV, a good decision is to have this chunk of code in a separate class and have both routines call it. However, whenever you call code outside of the routine as opposed to calling code in the same routine, some execution speed is lost. For reports churning through millions of transactions this lost speed might be noticeable. Any advice how to optimize specifically speed?

What you are asking is very similar to Inline function in C.

In Caché, macros and/or preprocessor directives are great for this role. Especially if the code size is small: ObjectScript Macros and the Macro Preprocessor

In this case you will avoid the overhead of calling goto, do, job, xecute, etc.

 

Example (procedure "swap")

Class dc.a Extends %RegisteredObject
{

ClassMethod swap(
  ByRef x,
  ByRef y)
{
  tmp=x,x=y,y=tmp
}

/// d ##class(dc.a).Test()
ClassMethod Test(= {1e7})
{
  #define swap(%x,%y) s ##unique(new)=%x,%x=%y,%y=##unique(old)
  
  s a=3,b=7  
  
  t=$zh  f i=1:1:tmp=a,a=b,b=tmp
  "inline procedure",?20,$zh-t," sec",!
  
  t=$zh  f i=1:1:swap
  "just a procedure",?20,$zh-t," sec",!
  
  t=$zh  f i=1:1:$$$swap(a,b)
  "macros procedure",?20,$zh-t," sec",!

  t=$zh  f i=1:1:..swap(.a,.b)
  "class method",?20,$zh-t," sec",!

swap() tmp=a,a=b,b=tmp
}

}

 ;dc.a.1
 ;Generated for class dc.a.  Do NOT edit. 09.06.2025 00:00:00PM
 ;;00000000;dc.a
 ;
Test(Nmethodimpl s:'($d(N)#2) N=1e7
  a=3,b=7  
  t=$zh  f i=1:1:tmp=a,a=b,b=tmp
  "inline procedure",?20,$zh-t," sec",!
  t=$zh  f i=1:1:swap
  "just a procedure",?20,$zh-t," sec",!
  t=$zh  f i=1:1:%mmmu1=a,a=b,b=%mmmu1
  "macros procedure",?20,$zh-t," sec",!
  t=$zh  f i=1:1:..swap(.a,.b)
  "class method",?20,$zh-t," sec",!
swap() tmp=a,a=b,b=tmp }
swap(x,ymethodimpl {
  tmp=x,x=y,y=tmp }

When implementing a sorting algorithm doing lots of swaps, this can increase the execution speed.

PS: And yes, avoid passing input/output parameters and class methods due to the high overhead of calling them.

Vitaliy Serdtsev · Jun 6, 2025 go to post
CREATE FUNCTION inLike(str VARCHAR(50), lstLike VARCHAR(50))
RETURNS BIT
PROCEDURE
LANGUAGE OBJECTSCRIPT
{
  set res = 0, ptr = 0
  while $listnext(lstLike,ptr,v{
    &sql(select case when :str like :v then else end into :like)
    if like {
      set res = 1
      quit
    }
  }  
  quit res
}

Usage:

select * from CustomersTable where inLike(CustomerName,$LISTBUILD('%Mark%','%John%','%an%'))=1
Vitaliy Serdtsev · Jun 4, 2025 go to post

Has it worked before? If so, then most likely there were some changes in the OS at the file/registry level.

First, try to run on the command line (see Registering Files):

>cd D:\DHC\DEVSOFTWARE\ENSEMBLE\BIN
D:\DHC\DEVSOFTWARE\ENSEMBLE\BIN>RegFiles.bat ALL

If it doesn't help, try select Repair to repair problems with the instance such as missing or corrupt files or registry entries: Reinstalling or Uninstalling Caché

Vitaliy Serdtsev · May 21, 2025 go to post

Great, that's something.

Can you show the exact query text and the class source code for the SQLUser.PA_Person table?

Vitaliy Serdtsev · May 21, 2025 go to post

In your question, yesterday you published the mgstat results for slow and fast servers. Now it looks like you've deleted this data, since I can't see it. Could you return them?

I noticed a very significant difference there for two parameters, namely routinebuffers and numberofcpus.

Vitaliy Serdtsev · May 21, 2025 go to post

Try to do my example and report the results. Also, try to run your query not in win sql, but in the InterSystems Management Portal.

Vitaliy Serdtsev · May 21, 2025 go to post
Class dc.a Extends %Persistent
{

Property As %String;

ClassMethod Test()
{
  &sql(truncate table dc.a)

  &sql(insert into dc.a(svalues('Hello'))
  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.a").%Display()

  !
  &sql(update dc.set s=s||' world' where %ID=1)
  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.a").%Display()
}

}

USER>##class(dc.a).Test()
ID      s
1       Hello
 
1 Rows(s) Affected
ID      s
1       Hello world
 
1 Rows(s) Affected
Can we see the error number and error text?
Vitaliy Serdtsev · May 19, 2025 go to post
If that's correct, is there a way to configure the JDBC connection to interpret this data using EUC-KR encoding?
No: Caché JDBC Connection Properties But even if JDBC had encoding settings, it wouldn't help you, because the 8-bit version of Caché doesn't support Korean and doesn't know anything about EUC-KR/KSC5601.

PS: I would consider switching to the Unicode version of Caché, which already has support for the Korean language.

Vitaliy Serdtsev · May 16, 2025 go to post
However, when I access the data through the Cache Management Portal, Cache Terminal, VSC, or IntelliJ, the Korean text appears broken, as I mentioned earlier.
Give an example of what you see in globals in the InterSystems Management Portal: System Explorer > Globals

Since you have an 8-bit version and not Unicode, you probably won't see the hieroglyphs (최봉남), but rather something similar to (ÃÖºÀ³²).

This is not corrupted data, just a string stored in KSC5601/EUC-KR encoding.

From Caché terminal (Unicode version, locale = korw (Korean, Korea, Unicode)):

USER><FONT COLOR="#0000ff">w $zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"최봉남"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"O"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"KSC5601"</FONT><FONT COLOR="#000000">)</FONT>
ÃÖºÀ³²
USER><FONT COLOR="#0000ff">w $zcvt</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008000">"ÃÖºÀ³²"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"I"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"KSC5601"</FONT><FONT COLOR="#000000">)</FONT>
최봉남

The same on Java:

System.out.println(newString("최봉남".getBytes(Charset.forName("EUC-KR")), Charset.forName("ISO-8859-1"))); // ÃÖºÀ³²
System.out.println(newString("ÃÖºÀ³²".getBytes(StandardCharsets.ISO_8859_1), Charset.forName("EUC-KR")));   // 최봉남
Vitaliy Serdtsev · May 15, 2025 go to post

When I run below code in the Cache terminal, it returns 0, so it seems to be the 8-bit version.

That's what I thought. I have the Unicode version installed, the rusw locale, and there are no problems at all.

 

Example

Class dc.a Extends %Persistent
{
Index is On s;
Property As %String;

/// d ##class(dc.a).Test()
ClassMethod Test()
{
  t=..%New()
  t.s="최봉남"
  
  t.%Save()
}
}

From any JDBC client:

select * from dc.a
Result:
ID s
1 최봉남

(When I check from the Management Portal, it shows as Latin1. If there's a more accurate way to verify this, please let me know.)

In SMP: System Administration > Configuration > National Language Settings > Locale Definitions
You should have something like kor8, enu8, eng8, etc.

Vitaliy Serdtsev · May 15, 2025 go to post

<FONT COLOR="#0000ff">Update </FONT><FONT COLOR="#008000">tablename </FONT><FONT COLOR="#000080">set </FONT><FONT COLOR="#008000">column1 </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#008000">column1 </FONT><FONT COLOR="#000000">|| </FONT><FONT COLOR="#008080">' world' </FONT><FONT COLOR="#000080">where </FONT><FONT COLOR="#000000">...</FONT>

Vitaliy Serdtsev · Apr 24, 2025 go to post

It seems that adding to favorites via the management portal itself has also stopped working. Interestingly, there is no error in this case.

Add to favorites in Management Portal

Vitaliy Serdtsev · Apr 18, 2025 go to post

IRIS 2025.1.CE: the error is the same.

Why the %Library.EntityProjectionUtil class is missing in the system is a good question for developers.

Vitaliy Serdtsev · Apr 18, 2025 go to post

Script Command Arguments:

Note:

Any ASCII (extended) character except NUL (000) can be produced via <ddd> where ddd is the decimal value of the character.

USER>w $a("<")
60
USER>w $a(">")
62

So, something similar is needed:

echo: off
send: s V=4 I (V<60>48!(V<62>57))&&(V<60>65!(V<62>90))&&(V<60>97!(V<62>122))  W A,?10,G,?30,B,!<CR>
wait for:USER>
Vitaliy Serdtsev · Apr 15, 2025 go to post

I join the question @Ashok.Kumar.

I did not find DP-422635 and DP-424156 among the published ones:

In addition, there are no warnings in the documentation that these methods are deprecated and no longer work: Calling Functions and Procedures from Python

Vitaliy Serdtsev · Mar 31, 2025 go to post

Initially, the question was asked in relation to Caché or/and Ensemble 2018.1, but not to IRIS.

Vitaliy Serdtsev · Mar 13, 2025 go to post

Another solution via $LISTFROMSTRING:

<FONT COLOR="#0000ff">set </FONT><FONT COLOR="#808000">s</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"item1"
</FONT><FONT COLOR="#0000ff">for </FONT><FONT COLOR="#808000">i</FONT><FONT COLOR="#000000">=2:1:5 </FONT><FONT COLOR="#800080">{
  </FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#808000">s</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#808000">s</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#008000">",item"</FONT><FONT COLOR="#000000"></FONT><FONT COLOR="#808000">i
</FONT><FONT COLOR="#800080">}
</FONT><FONT COLOR="#0000ff">set </FONT><FONT COLOR="#808000">mylist</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#0000ff">$listfromstring</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#808000">s</FONT><FONT COLOR="#000000">)
</FONT><FONT COLOR="#0000ff">zwrite </FONT><FONT COLOR="#808000">mylist </FONT><FONT COLOR="#008000">; mylist = $lb("item1","item2","item3","item4","item5")</FONT>
Vitaliy Serdtsev · Mar 10, 2025 go to post

IRIS for Windows (x86-64) 2024.3 (Build 217U) Thu Nov 14 2024 17:59:58 EST

Or "Include EnsUtil"

Now you can do it like this:

<FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%BigData.ShardedSQL</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">ClassNameToTableName</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#808000">pClassName</FONT><FONT COLOR="#000000">)</FONT>
Vitaliy Serdtsev · Mar 10, 2025 go to post
USER>w $zv
IRIS for Windows (x86-64) 2024.3 (Build 217U) Thu Nov 14 2024 17:59:58 EST

USER>w $$GetEnvironment^%apiOBJ("collation","%Library.String",.collval),! zw collval
1
 
USER>w $$GetEnvironment^%apiOBJ("collation","dc.Username",.collval),! zw collval
1
 
USER>zn "%SYS"
 
%SYS>w $$GetEnvironment^%apiOBJ("collation","%Library.String",.collval),! zw collval
1
 
%SYS>w $$GetEnvironment^%apiOBJ("collation","%Library.Username",.collval),! zw collval
1
Vitaliy Serdtsev · Mar 10, 2025 go to post

Strangely, I had no issues with the %Library.Username type. I didn't explicitly specify the collation anywhere: neither in the data type class nor for the Namespace-wide.

Namespace '%SYS':

<FONT COLOR="#000080">Class %Library.Username Extends %String
</FONT><FONT COLOR="#000000">{

</FONT><FONT COLOR="#000080">Parameter </FONT><FONT COLOR="#000000">MAXLEN </FONT><FONT COLOR="#000080">As </FONT><FONT COLOR="#000000">INTEGER = </FONT><FONT COLOR="#000080">160</FONT><FONT COLOR="#000000">;

}</FONT>

Namespace 'USER':

<FONT COLOR="#000080">Class dc.Username Extends %String
</FONT><FONT COLOR="#000000">{

</FONT><FONT COLOR="#000080">Parameter </FONT><FONT COLOR="#000000">MAXLEN </FONT><FONT COLOR="#000080">As </FONT><FONT COLOR="#000000">INTEGER = </FONT><FONT COLOR="#000080">160</FONT><FONT COLOR="#000000">;

}</FONT>

<FONT COLOR="#000080">Class dc.a Extends %Persistent </FONT><FONT COLOR="#000000">{

</FONT><FONT COLOR="#000080">Index </FONT><FONT COLOR="#000000">is1 </FONT><FONT COLOR="#000080">On </FONT><FONT COLOR="#000000">s1;

</FONT><FONT COLOR="#000080">Index </FONT><FONT COLOR="#000000">is2 </FONT><FONT COLOR="#000080">On </FONT><FONT COLOR="#000000">s2;

</FONT><FONT COLOR="#000080">Index </FONT><FONT COLOR="#000000">is3 </FONT><FONT COLOR="#000080">On </FONT><FONT COLOR="#000000">s3;

</FONT><FONT COLOR="#000080">Property </FONT><FONT COLOR="#000000">s1 </FONT><FONT COLOR="#000080">As %String</FONT><FONT COLOR="#000000">;

</FONT><FONT COLOR="#000080">Property </FONT><FONT COLOR="#000000">s2 </FONT><FONT COLOR="#000080">As %Username</FONT><FONT COLOR="#000000">;

</FONT><FONT COLOR="#000080">Property </FONT><FONT COLOR="#000000">s3 </FONT><FONT COLOR="#000080">As dc.Username</FONT><FONT COLOR="#000000">;

</FONT><FONT COLOR="#000080">ClassMethod </FONT><FONT COLOR="#000000">Test() {   </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#000000">..</FONT><FONT COLOR="#0000ff">%KillExtent</FONT><FONT COLOR="#000000">()      </FONT><FONT COLOR="#0000ff">f </FONT><FONT COLOR="#808000">s</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#008000">"joefu"</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#008000">"JoeFu" </FONT><FONT COLOR="#800080">{     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#808000">t</FONT><FONT COLOR="#000000">=..</FONT><FONT COLOR="#0000ff">%New</FONT><FONT COLOR="#000000">()     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#808000">t</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">s1</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#808000">s     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#808000">t</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">s2</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#808000">s     </FONT><FONT COLOR="#0000ff">s </FONT><FONT COLOR="#808000">t</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">s3</FONT><FONT COLOR="#000000">=</FONT><FONT COLOR="#808000">s     </FONT><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#808000">t</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">%Save</FONT><FONT COLOR="#000000">()   </FONT><FONT COLOR="#800080">}

  </FONT><FONT COLOR="#0000ff">zw </FONT><FONT COLOR="#000000">^dc.aD,^dc.aI }

}</FONT>

select FIELD_NAME,DATATYPE,COLLATION_FUNCTION,MAXLEN from %Library.SQLCatalog_SQLFields('dc.a')
FIELD_NAMEDATATYPECOLLATION_FUNCTIONMAXLEN
ID%Library.BigInt(null)(null)
s1%Library.StringSQLUPPER50
s2%Library.UsernameSQLUPPER160
s3dc.UsernameSQLUPPER160
x__classname%Library.RawString(null)(null)
select INDEX_NAME,FIELDS from %Library.SQLCatalog_SQLIndices('dc.a')
INDEX_NAMEFIELDS
is1$$SQLUPPER({dc.a.s1})
is2$$SQLUPPER({dc.a.s2})
is3$$SQLUPPER({dc.a.s3})
USER>##class(dc.a).Test() ^dc.aD=2 ^dc.aD(1)=$lb("","joefu","joefu","joefu") ^dc.aD(2)=$lb("","JoeFu","JoeFu","JoeFu") ^dc.aI("is1"," JOEFU",1)="" ^dc.aI("is1"," JOEFU",2)="" ^dc.aI("is2"," JOEFU",1)="" ^dc.aI("is2"," JOEFU",2)="" ^dc.aI("is3"," JOEFU",1)="" ^dc.aI("is3"," JOEFU",2)=""
Vitaliy Serdtsev · Feb 28, 2025 go to post

See Class Reference: Class %Stream.FileBinaryGzip Extends FileBinary Class %Stream.FileBinary Extends %Stream.Object

Hence %Stream.FileBinaryGzip is already the heir of %Stream.Object.