go to post Joel Solon · Dec 8, 2022 It's not a big difference between Studio and VS Code - ObjectScript here. Studio automatically does the #dim for you when you do a %New() or %OpenId(), and VS Code - ObjectScript doesn't. But #dim is still necessary in both IDEs for referenced or returned objects: set person = ##class(Simple.Person).%New() // Studio WILL provide code completion for person, VS Code WON'T #dim address as Simple.Address // without #dim, neither Studio nor VS Code will provide code completion for address set address = person.Address #dim rs as %SQL.StatementResult set rs = statement.%Execute(args) // you'll get code completion for rs thanks to #dim
go to post Joel Solon · Dec 2, 2022 Since Trigger code is called after validation and constraint checking, a trigger should not be used to change column values. David's solution is better.
go to post Joel Solon · Dec 2, 2022 I think you get everything from secondary superclass(es) except indexes, storage, and relationships.
go to post Joel Solon · Nov 1, 2022 Thanks Michael. You could code it the oop way, and use $sortbegin on all the index globals for your multiple tables, which means you'd have to know or look up what the index global names are (since they're not always ^D and ^I anymore), and test 1000000 inserts (main table and referenced tables) with the index build deferred to the end, and time it to see how long it takes. And then code it the sql way, inserting the same data into the multiple tables using %NOINDEX, and calling %BuildIndices() on all the classes at the end, and time it to see how long that takes. The sql way is supposed to be faster...
go to post Joel Solon · Nov 1, 2022 @Alex Woodhead Why are you using $sortbegin on the ^D global? Just to show it's possible in this demo? Or are you recommending that general approach? It seems to me that the solution to the original question would be allowing the data to save normally (not using $sortbegin on the ^D global), and using $sortbegin on the ^I global and discarding those updates.@Michael Fortunato Please tell us the reason for wanting to do this. It can't be that you want the index to be permanently out of sync with the data. Perhaps it's for performance for many inserts? If so, switching to a SQL approach with %NOINDEX (as @David.Satorres6134 suggested) is a good idea.
go to post Joel Solon · Aug 15, 2022 Would <foreach> help here? https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...
go to post Joel Solon · Aug 15, 2022 I love the Dev Community and how we all help each other learn more and more!
go to post Joel Solon · Jul 27, 2022 So this thread has clarified that the transaction that you read about in the docs is the transaction inside %Save(), and %OnSaveFinally() is a callback for %Save(). Your original question seems to be asking if the TCOMMIT command itself triggers a callback, but it doesn't. You could of course add your own code right after the TCOMMIT, but I guess that's not what you're looking for with this question.
go to post Joel Solon · Mar 25, 2022 A little bit more detail. The queries in %SYSTEM.License are not defined as [SqlProc]s. Therefore, they can't be called from outside IRIS, including from Python. To get the information returned by these queries in Python, you should write your own method in ObjectScript, that runs the query with the (deprecated) %Library.ResultSet class. As you loop through the results: If you're comfortable with JSON, create a JSON structure like this [ { first result}, {second result}, …, {nth result} ] and then just return that, and then handle the JSON in Python. If you want to return a SQL result set to Python (which is what would be returned if you could actually call the UserListAll query), read about creating custom queries here: https://docs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic.cls?&LIBRARY=%25SYS&CLASSNAME=%25SQL.CustomQuery
go to post Joel Solon · Mar 17, 2022 ...and it appears that Mr C is also trying to sneak in a new abbreviation for ObjectScript: ISOS.
go to post Joel Solon · Jan 4, 2022 Ah, I misinterpreted "this alias" in your post! So you meant (I added italicized text): "I like to define :sql as a way to launch the shell and execute a statement - so that means this built-in :sql alias should be renamed by InterSystems to something else!! or be removed." At least aliases defined in .iris_init override any built-in aliases.
go to post Joel Solon · Jan 4, 2022 I have one older IRIS instance (unreleased v2021.1 with some Python extras) that has the following aliases built in. The :sql alias doesn't run Execute() like it seems to do on yours. :py Do $system.Python.Shell() :mdx Do $system.DeepSee.Shell() :sql Do $system.SQL.Shell() :tsql Do $system.SQL.TSQLShell()
go to post Joel Solon · Jan 3, 2022 Here's some info that was inadvertently removed from the docs, but will be returning soon: On Unix systems, if a file named ~/.iris_init exists, it is read when a terminal session is initiated. Only lines starting with :<command> are processed. All other lines are ignored. This file accepts only :alias commands, which enables you to store favorite command abbreviations there.Example of a ~/.iris_init file: # Initial aliases :alias % zn "%SYS" :alias load Do $System.OBJ.Load("$1",$S("$2"="":"ck",1:"$2")) :alias ut Do ##class(%UnitTest.Manager).RunTest("$1")
go to post Joel Solon · Dec 30, 2021 :alias sql do $system.SQL.Shell() :alias err do $system.Status.DisplayError($1)
go to post Joel Solon · Dec 29, 2021 VS Code - ObjectScript doesn't prevent <SUBSCRIPT> errors. For example, the statement set b(x) = c can't be checked by the IDE since it doesn't know if the value of x will be "" or not at runtime.
go to post Joel Solon · Dec 21, 2021 Nice article about an important question: when should you touch the storage definition? Some comments on the scenarios (with sound effects!). The only modifications I'd make to the bookshelf analogy is that there are gazillions of shelves (every person gets their own shelf) using the mapping of what type of book goes in each slot. Scenario 1: You are creating a class, and adding, deleting, and renaming properties. If there's any data for the class, it is test/temporary data and can be deleted at will. As Vivian saw, deleting a property doesn't change the storage definition (the slot for the deleted property is left unused), and renaming a property is really a deletion (old slot unused) followed by an addition (new slot). Once you get the class the way you want it for release, you can safely delete the storage definition (since there's no real data) and the next compilation will create a fresh one, with no unused slots. No danger (cue happy music). Scenario 2: You are editing an existing class with real stored data. If you rename any property (new or existing, with or without data) it's best practice to rename the storage definition slot also before your next compile. If it's a newly added property without data and you don't bother to rename the slot, it's OK, but you now have a wasted slot that will never be used, and a new slot for the data you'll eventually start saving. Why not rename the slot right away? On the other hand, if it's a property that has data, you must rename the storage slot, or the data for that property will no longer be accessible, and new data for the renamed property will go in a different slot. Any danger is prevented by renaming the property and storage definition slot at the same time (cue triumphant marching music). Scenario 3: You delete a property with real stored data. As before, the old slot is left unused. Any new property added later will not use that slot (no double-booking; new data won't ever be added there). But the real question is: Why are you deleting the property? Do you not care about that data anymore? If so, why aren't you deleting the data first? And by deleting the data, I don't mean editing the global directly (which I think is what Vivian meant by "don't do this."). But it's not dangerous to the table to use SQL to delete Book B from every bookshelf before deleting the property:update schema.table set property = null(cue computer bleeps). Editing the name of any unused slot in the storage definition and adding "-unused" to make things clear could be OK but it's definitely not intended for that use. I'm not sure it's necessary to do anything in this case; If I see a slot in the storage definition named XYZ and there's no property XYZ, I know it's an unused slot. Maybe preceding the storage definition with a comment section would be cleaner: /* unused slots XYZ (as of 1/1/2020) ABC (as of 6/1/2021) */ Please let me know if it's not clear, or if I missed a scenario.
go to post Joel Solon · Nov 10, 2021 I added Steve's suggestion, not because he asked twice, but because I owe him some money.
go to post Joel Solon · Nov 10, 2021 Thanks to @Muhammad Waseem I'm posting an updated version of the "Cheat Sheet."
go to post Joel Solon · Nov 5, 2021 Very strange! I was never on the standards committee. I started using MUMPS in 1987, and I remember it differently ($next being replaced by $order). Let me check the archives... My 1981 copy of the Standard MUMPS Pocket Guide states that variables can have only non-negative integer subscripts, and lists $next (returning -1 if no more subscripts exist), but there's no mention of $order. My 1983 copy of the Pocket Guide (based on the 1977 ANSI Standard) states that variables can use any string as a subscript and lists $order (both noted as approved extensions of the Standard; $order using "" as both the seed and the flag for no more subscripts), and $next is still listed. My 1987 copy of the Pocket Guide (based on the 1984 ANSI Standard) has the same info as the 1983 Guide, except the approved extensions are now part of the Standard. My 1995 copy of the Pocket Guide (based on the 1995 ANSI Standard) lists the 2 argument form of $order, but $next (having been deprecated) is not listed. Public viewing of the Solon Archives available by appointment only ;-) https://www.youtube.com/watch?v=rIz_xhYK2Mo
go to post Joel Solon · Oct 28, 2021 All I can say is Wow! I experienced many of the same things over my career, but I was living in safe, protected, training-room-land, not the real world of development like Nigel. Great article! I'll just note that Nigel says "might" in the title. One thing that confused me, Nigel. You wrote "If one of the early MUMPS creators had called $order "$next", it would immediately be recognizable as Next()...". But I know that you know that the original $order was called $next.