Marc Mundt · Aug 31, 2021 go to post

You can view the source for %syPidtab.inc in the System Management Portal using System Explorer >> Routines or by opening it in Studio.

Marc Mundt · Aug 31, 2021 go to post

You can use the %Dictionary classes to get details of the class and methods:

USER>do $System.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
 
The command prefix is currently set to: <<nothing>>.
Enter <command>, 'q' to quit, '?' for help.
[SQL]USER>>SELECT FormalSpec FROM %Dictionary.MethodDefinition WHERE parent='My.Test.Class' AND Name='TestMethod'
1.      SELECT FormalSpec FROM %Dictionary.MethodDefinition WHERE parent='My.Test.Class' AND Name='TestMethod'
 
FormalSpec
param1:%String,param2:%Numeric
 
1 Rows(s) Affected
statement prepare time(s)/globals/cmds/disk: 0.0033s/321/1482/0ms
          execute time(s)/globals/cmds/disk: 0.0006s/3/385/0ms
                          cached query class: %sqlcq.USER.cls14
---------------------------------------------------------------------------
[SQL]USER>>
Marc Mundt · Aug 22, 2021 go to post

Create a BS that sends messages to BO every X seconds - it makes production more complex and also queues might not guarantee that the method is executed on schedule.

You could try submitting the message to the head of the queue to be sure it gets processed right away.

Marc Mundt · Aug 18, 2021 go to post

A couple of things...

You'll want to use "O" (output) mode instead of "I" (input) mode:
write $zconvert("Flávio","O","HTML")

However, I see that this still doesn't replace the "á". But if I add an "&" it replaces it with "&amp;" as expected:
write $zconvert("Flávio&","O","HTML")
The table at the bottom of this section in the documentation lists which characters are encoded into entities in HTML mode.

Marc Mundt · Jul 29, 2021 go to post

I'll be interested to see others' thoughts on this as well, but one approach is:

  • Create a new empty database for the globals
  • Use GBLOCKCOPY or MERGE to copy each of the globals from the current DB to the new globals DB. I believe GBLOCKCOPY is faster than MERGE.
  • After they are copied/merged to the new DB kill the globals in the currrent DB. This then becomes your routines DB.

Or you can do the opposite and export all of your routines from the current DB, import them into a new routines DB, then delete them from the current DB which becomes your globals DB. This would be faster than the first approach unless your globals are really small.

Marc Mundt · Jul 27, 2021 go to post

As an alternate approach, you could use the Lookup() function to check if the value exists in a lookup table. The advantage is that adding entries to a lookup table is easier/cleaner than updating your DTL with every new entry.

Marc Mundt · Jul 23, 2021 go to post

Two more options. Haven't tested how they perform.

set lst = ""
for i=1:1:someNumber {
    set $LIST(lst,i)=myval
}
set str = $listtostring(lst,",")
set lst = ""
for i=1:1:someNumber {
    set $PIECE(lst,",",i)=myval
}
Marc Mundt · Jul 12, 2021 go to post

Here's a working example using <img> in a <table>. I don't think you can put an <img> inside an <item> or inside another <img>.

<table orient="col">
            <block width="40%">
                    <img src="http://localhost/logo.jpg" contentHeight="0.56in" contentWidth="2.33in" style="text-align:left"/>
            </block>
            <block width="40%">
                <table orient="col">
                        <item field='#(..pagetitle)#'/>
                </table>
            </block>
            <block width="20%" style="text-align:right;">
                  <item field='#(..subtitle)#'/>
             </block>
</table>
Marc Mundt · Jun 30, 2021 go to post

It would be good to have a look at the final value of tSQL in performUpdate.

Marc Mundt · Jun 23, 2021 go to post

Here is the section in the docs that explains why this is happening and why @Eduard Lebedyuk asked if that class is persistent.
 

Business Process Execution Context

The life cycle of a business process requires it to have certain state information saved to disk and restored from disk, whenever the business process suspends or resumes execution. This feature is especially important for long-running business processes, which may take days or weeks to complete.

A BPL business process supports the business process life cycle with a group of variables known as the execution context. InterSystems IRIS automatically save the variables in the execution context and restores them each time the BPL business process suspends and resumes execution.

Marc Mundt · Jun 14, 2021 go to post

It seems like this approach would still work with a poolsize > 1. Of course each worker job will decide on its own if it should throttle or not.

Marc Mundt · Jun 10, 2021 go to post

There's no option for %DisplayFormatted to split the results into multiple parts automatically. You would need to write a custom method to do your CSV output with the logic you need. I can post some sample code that outputs CSV if that would be helpful.

8 hours for 16 million records at ~140 bytes/record seems really slow. I just did a test on a slow Windows VM and for a simple "SELECT *" for 16 million records @ 150 bytes/record, %DisplayFormatted took about 18 minutes to output the 2.4 GB CSV.

I suggest you contact the WRC to help look at where the bottleneck is.

Marc Mundt · Jun 9, 2021 go to post

In your assign action, there is a leading space in the property name:

<assign value='source.AttendingClinicians.GetAt(st).Code' property=' npicode' action='set' />
Marc Mundt · May 24, 2021 go to post

%XML.Reader and %XML.Document won't automatically update the original stream. You need to use %XML.Writer to output the %XML.Document into a stream.

set writer=##class(%XML.Writer).%New()
set outStream=##class(%Stream.GlobalCharacter).%New()
set tSC=writer.OutputToStream(.outStream)
set tSC=writer.Document(document)
write "Stream:[",outStream.Read(3000000),"]",!
Marc Mundt · May 21, 2021 go to post

If there aren't any delimiters in your input string, then this will do it:

set result="233434345543433400110"
for i=1:4:$LENGTH(result) {
    write $E(result,i,i+3),!    
}

Output:

2334
3434
5543
4334
0011
0
Marc Mundt · May 21, 2021 go to post

[1,2,,3] is arguably more ambiguous than a trailing comma, and there are some precedents for (if and) how to treat trailing commas.

On the other hand, I just tested both cases in Firefox using JSON.parse() and they both fail. Browsers tend to be pretty tolerant of bad stuff, so the fact that Firefox won't accept trailing commas makes a good case for IRIS not allowing trailing commas either.

Strangely, Firefox apparently allows trailing commas in JavaScript, but not in JSON.

Marc Mundt · May 20, 2021 go to post
set obj1={"Value":123, }  --> gives a SYNTAX

Since this is the syntax for a "JSON literal", and only happens in ObjectScript code, it makes sense to me that IRIS would force the developer to do the right thing.

%FromJSON has to deal with JSON that comes from other sources, so it makes sense that it is more forgiving of bad practices.

Marc Mundt · May 20, 2021 go to post

File Specs for services support wildcards, but not the complex time stamp specifications that are used for outputting filenames from an operation.

File Spec
Filename or wildcard file specification for file(s) to retrieve. For the wildcard specification, use the convention that is appropriate for the operating system on the local InterSystems IRIS Interoperability machine.

https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View…

Marc Mundt · May 20, 2021 go to post

Have a look at the Record Mapper -- you can create a spec for your target flat file format, and then map to that as the target format in your DTL.

Marc Mundt · May 14, 2021 go to post

I haven't tested the code below, but in your subclass you can override MakeRequest(), call the original superclass version of MakeRequest() and then you should be able to set the header before returning from your custom method.

Something like this:

Method MakeRequest(pRequestMethod As %String, pPayload, pRequestPath As %String, pQueryString As %String, ByRef pHeaders) As %RegisteredObject
{
    set ..%HttpRequest = ##super(pRequestMethod, pPayload, pRequestPath, pQueryString, .pHeaders)
    do ..%HttpRequest.SetHeader("Some Header Name", "Some Header Value")
    return ..%HttpRequest
}