David Hockenbroch · Sep 15, 2025 go to post

FYI, in your "Building SQL In Strings" section, you can also still use %SQL.Statement like this:

set stmt = ##class(%SQL.Statement).%New()
// Note the question mark in the query.set query = "SELECT Name, Age FROM Patient WHERE ID=?"set sc = stmt.%Prepare(query)
// You can add error handing here if the above status results in an error// Providing variables to the %Execute method will insert them where the question marks are in the query, in orderset rs = stmt.%Execute(id)
David Hockenbroch · Sep 11, 2025 go to post

Really you'd want to set a variable equal to the $TLEVEL at the start of your try, then in the catch calculate the difference between the starting $TLEVEL and the current $TLEVEL, then do that many TROLLBACK 1s.

David Hockenbroch · Sep 10, 2025 go to post

Combining what you said about error handling and transactions and also returning a status, a very basic outline for a lot of methods could be something like:

try{
    TSTART//Do stuff hereTCOMMITreturn$$$OK
}
catch ex{
    if$TLEVEL > 0{
        TROLLBACK
    }
    return ex.AsStatus()
}

Some of us who write articles could do a better job of making this easier for you too, though. We like to use short forms of certain things, like {} and [] which are ##class(%Library.DynamicObject) and ##class(%Library.DynamicArray). I try to remember to use the latter in my articles just because it makes it easier to find the thing I'm talking about in the documentation. There are cases like that which are technically correct, but make it harder for beginners to learn.

David Hockenbroch · Aug 22, 2025 go to post

Your NewsGetItem method has two parameters, version and id, but the route you have defined for it only has one parameter, id. The parameter lists need to match up and be in the same order. Try taking the version parameter our of the NewsGetItem class method.

David Hockenbroch · Aug 20, 2025 go to post

In this case, you'd probably have to create a class method in ObjectScript that changes the namespace, then call it using classMethodVoid() from the IRIS native SDK. But you'd have to make sure the necessary class method exists in all of the namespaces you want to change to and from, including %SYS.

David Hockenbroch · Aug 20, 2025 go to post

I just now took a closer look at this because of a comment made on one of my ideas on the idea portal, and that's great news for us! Our software is an ERP system, and we have some customers who have multiple locations that they sell things out of. We generally have them share one code database, but different global databases. The old way, where it stored the table tuning statistics with the code, made it unusable for us because each of those locations would have different orders, invoices, customers, etc., so tuning the table would help one namespace and potentially harm the others!

David Hockenbroch · Aug 20, 2025 go to post

In ObjectScript, you would do:

new$NAMESPACEset$NAMESPACE = "USER"

In embedded Python, you can execute those commands using iris.execute:

import iris
iris.execute('new $NAMESPACE')
iris.execute('set $NAMESPACE = "USER"')

I am not far enough into embedded Python to know if that's considered a best practice or if there's another way, but it does work. Here are my results in a Python shell terminal session:

>>> print(iris.system.SYS.NameSpace())
USER
>>> iris.execute('new $NAMESPACE')>>> iris.execute('set $NAMESPACE = "%SYS"')>>> print(iris.system.SYS.NameSpace())%SYS
David Hockenbroch · Aug 15, 2025 go to post

This seems to work for positive posix times, but I'm not sure why the 846,976 microsecond offset is required. Maybe someone who understands this subject better can answer that one. All math, though, no string manipulation.

set newposix = ##class(%Library.PosixTime).LogicalToDisplay(posix-(posix#1000000)+846976)
David Hockenbroch · Aug 12, 2025 go to post

There are some naming conventions in the documentation already. Here's one example. I think there used to be more. I know there was one for Zen pages that suggested naming methods based on what was client side or server side or a Zen method. I thought there was also one that explained how things were named in the system classes, but I can't find that one in the current documentation.

I have no strong opinion about whether they are (or were) right or wrong. I think we just need to be aware that some of these are still out there, and people may be using them.

David Hockenbroch · Jul 22, 2025 go to post

Vachan, that depends in part on what exactly you are doing in the terminal at the time. If you are running a method or routine that includes logging an exception, that will happen in the terminal just like it would anywhere else.

David Hockenbroch · Jul 13, 2025 go to post

Thank you for the advice! I will try to learn about all of those things so I can improve this.

David Hockenbroch · Jul 9, 2025 go to post

You can log the exception in your catch block for exactly the result you're looking for, if I understand your request correctly.

try{
    //Your code here.
}
catch ex{
    //The below line will add the exception to the application error log.//Code will continue to execute after the catch block.do ex.Log()
}
David Hockenbroch · Jul 9, 2025 go to post

Ronald, if that's your exact code, it may be because you have it as %Request instead of %request, lowercase r. Because %Request is undefined, it can't tell you whether %Request.Data("action",1) is undefined or not. Try it with %request.

David Hockenbroch · Jun 30, 2025 go to post

As a point of clarification, property names ARE case sensitive in ObjectScript, but in SQL, column names ARE NOT case sensitive. You aren't allowed have a property named "name" and a property named "Name" because they would be ambiguous when doing SQL queries.

David Hockenbroch · Jun 30, 2025 go to post

Versions that old used to install all the documentation locally. I forget what options had to be selected in the installer because it's been a while, but if you run it, you should have the option somewhere. Then you should be able to click the Cache icon in your system tray and click on "Documentation".

David Hockenbroch · Jun 27, 2025 go to post

Do you mean the format as in HL7, FHIR, etc.? There are specific ContentType settings for those in the specification, I believe.

  • If the message is a "vertical bar" encoded HL7 v2.x message, the content type SHALL be:     x-application/hl7-v2+er7
  • If the message is an XML encoded HL7 v2.x message, the content type SHALL be:     x-application/hl7-v2+xml
  • If the message is an XML encoded HL7 v3 message, the content type SHALL be:     x-application/hl7-v3+xml
  • If the message is an XML encoded FHIR message, the content type SHALL be:     x-application/fhir+xml
  • If the message is a JSON encoded FHIR message, the content type SHALL be:     x-application/fhir+json
  • If the message is a CDA document, the content type SHALL be:     x-application/xml+cda
David Hockenbroch · Jun 27, 2025 go to post

In the %SYS namespace, you can query the table Security.Applications and check the type column. If you do this in the system management portal in display mode, the Type column will start with "System". In logical mode, though, it will be a number. 1 is System, 2 is CSP Application, 4 is a privileged routine application, and 8 is a client application, and if an application is more than one of those things, the Type column is their sum. For example, if it's a System applcation AND a CSP application, the type will be 3. That complicated things, but fortunately since the 1 is the only odd number and it signified system applications, we can use the modulus function to identify system applications as follows.

select * from security.applications where {fn MOD(type,2)} = 1

Also, at the risk of self-promotion, I wrote an article detailing more about managing applications programatically a while back. You can find it here.

David Hockenbroch · Jun 27, 2025 go to post

Here's an example of how we use the relationship between namespaces and databases.

My company sells ERP software for the millwork industry. Our customers sell building materials to contractors, distributors, etc. Some of our customers have multiple locations throughout the country. For those customers, we will usually set up a different namespace for each of those locations. Each of those namespaces is set up to have their own database for their data, but the all share the same database for routines because while they all have different data, like customers, orders, invoices, etc., the same set of code is running all of them.

David Hockenbroch · Jun 26, 2025 go to post

I have done those two, plus in certain cases a "CreatedBy" and "LastUser" that are automatically computed to the $USERNAME in insert and on insert/update.

David Hockenbroch · Jun 26, 2025 go to post

Whoops, I replied to the wrong comment somehow. Sorry!

Edit: for some reason when I clicked on the Reply button on Evgeny's comment above, it was initially showing this reply under Sergei's post below. Then when I left the page and came back, it was in the right place. Firefox being weird on me, I guess.

David Hockenbroch · Jun 11, 2025 go to post

@Jude Mukkadayil in one of your posts here, you mentioned this error:

[SQLCODE: <-415>:<Fatal error occurred within the SQL filer>]

[%msg: <Error occurring during UPDATE in table 'SQLUser.PA_Person': $ZE=<LIST>%SQLUpdate+40^User.PAPerson.1>]

According to this documentation, that could be a runtime error in some trigger code. In your User.PA_Person class's ObjectScript, you probably have a trigger defined that is causing issues for you. If so, can you post the code for the trigger(s) in that class?

David Hockenbroch · Jun 3, 2025 go to post

I grew up in Mifflintown, PA, just a couple hours' drive from Lancaster. We used to make weekend trips to Lancaster and see plays at Sight & Sound and some of the other touristy stuff around there.

David Hockenbroch · Jun 3, 2025 go to post

I'm David Hockenbroch, and I'm based out of Memphis Tennessee. I'm a senior analyst here at WoodWare, so I get into all kinds of things. Lately that includes spending a lot of time considering how to get some really old pieces of software that were written in VB6 or using Zen pages into something that's supported now.

I'm a big food person, so Memphis is a good place for me! I also enjoy being outside or taking in a good story, whether that's a movie, book, TV show, or even a well-written videogame.

I will not be at READY 2025. I look at the session list every year, and it seems very healthcare-focused. I'm not in health care, so I always question whether it's worth the trip for me. We write business software. I do typically catch up on some of the keynotes online, though.