go to post Julius Kavay · Jul 28, 2023 OK, one can short down those 20 bytes into 17 and we end up with 64 bytes. ClassMethod IsValid(x) { 1 s z=x,x=$replace($tr(x,$tr(x,"()")),"()","") g 1:x'=z q x="" } Again, speed wasn't asked
go to post Julius Kavay · Jul 28, 2023 OK, I start with 47 chars... unfortunately, I have to add 20 chars more for that (stupid) extra requirement of ignoring characters like {, [, <, etc. therefore end up with 67 chars ClassMethod IsHalfValid(x) { 1 s z=x,x=$replace(x,"()","") g 1:x'=z q x="" } ClassMethod IsFullValid(x) { 1 s z=x,x=$replace($zstrip(x,"*e",,"()"),"()","") g 1:x'=z q x="" } Speed was'n asked...
go to post Julius Kavay · Jul 27, 2023 In the mean time the answer is already given by Mr Maslennikov and others, but to shorten your runtime, you could also try a "variablenless" loop, maybe this gives you some seconds more... The emphasis is on "maybe". // if you have null-subscripts enabled if $d(^YYY(""))!1 for i=0:1 {quit:$order(@$zr)=""} write i // if null-subscripts are not enabled if $d(^YYY(-9E18))!1 for i=0:1 {quit:$order(@$zr)=""} write i // of course, you can do that on any arbitrary level too if $d(^YYY(1,2,3,""))!1 for i=0:1 {...} write i // the value of -9E19 ist just for explanation, use a value suitable for your needs May I ask for the background, why do you need that node count?
go to post Julius Kavay · Jul 27, 2023 Caution, backward $order() is always slower than forward $order(). If you need the last (hopefully few) entries, than it's OK to use a backward-$O() but running (counting) from the bottom to the top over several millions of nodes is definitely not an effective run.
go to post Julius Kavay · Jul 26, 2023 As others already wrote, write $order(^$GLOBAL("")) gives you the first global name accessible from a given namespace. Usually, this will be a percent-global (^%...) but if you want to get the first (or all) global, which resides in a given database, the do the same as above but with extended global access set dir = "^^c:\databases\mydb\" // "^^" and "the path to your CACHE/IRIS.dat file" write $order(^$|dir|GLOBAL(""))
go to post Julius Kavay · Jul 24, 2023 There are several possibilities, using WinSCP from Windows, Linux and Samba, etc. But if "using Cache codes" (Objectscript) is a requirement, then the simplest way is: open a TCP-(server)port on the one end and a TCP-(client)port on the other end, write and read the data, close the connections. Voila. The job is done. I do not see any problem there. OK, maybe you need to open those ports. And do not forget, USB-Sticks exists too ;-))
go to post Julius Kavay · Jul 22, 2023 Yes, accepts a file too, but as the following test shows, it does not make any difference... a parsing error remains parsing error USER>set fn="/tmp/mytest.json" USER>open fn:"nw":1 if $test { use fn write "[0.1, .2]",! close fn write "OK" } else { write "Houston, we have..." } OK USER>write {}.%FromJSON(fn) <THROW>%FromJSON+38^%Library.DynamicAbstractObject.1 *%Exception.General Parsing error 3 Line 1 Offset 7 USER 2e1> So where is that forgiving Cache/IRIS version?
go to post Julius Kavay · Jul 21, 2023 Do you have a code snippet for us? Something like write mylist.%IsA("%ListOfDataTypes") --> 1 set item = mylist.%GetAt(2) // // Now the big question: what do you (want to) do with this item? // // do you try to lock a global: lock ^myGlobal(item) ? // do you try to open (a possible locked) Object: set obj=##class(some.class).%OpenId(item [,4]) ? // something else?
go to post Julius Kavay · Jul 21, 2023 May I ask, which Cache or IRIS version you use? USER>write $zv IRIS for UNIX (Ubuntu Server LTS for x86-64) 2021.2 (Build 649U) Thu Jan 20 2022 08:49:51 EST USER>write ##class(%DynamicAbstractObject).%FromJSON("[0.1, .2]") <THROW>%FromJSON+38^%Library.DynamicAbstractObject.1 *%Exception.General Parsing error 3 Line 1 Offset 7 USER 2e1> As you see, my IRIS is by far not so forgiving... ☹
go to post Julius Kavay · Jul 18, 2023 Nice, now we know nearly everything, except the most important info: what is the content of pField? I assume, pObject contains the above JSON, i.e. set pObject = {"priority": "2", "lastmodifieduser": "PORTAL", "assignedto": "jdoe01 STAFF", ... }
go to post Julius Kavay · Jul 18, 2023 I'm not aware of any $ISJSON() or similar named function but you can easily make your own ClassMethod IsJSON(str) { try { ret:{}.%FromJSON(str) 1 } catch e { ret:e.Code=3 0 throw e } } set a="{name:""John Doe"" " set b="{""name"":""John Doe"" }" write ##class(some.class).IsJSON(a) --> 0 write ##class(some.class).IsJSON(b) --> 1 write ##class(some.class).IsJSON() --> <UNDEFINED>zIsJSON+1^... *str
go to post Julius Kavay · Jul 17, 2023 Absolutely right. It's more readable, without stumbling over millions of quotes and parenthesis during constructing (concatenate) the name of that globals ;-) I used the "string version" to show him/her, the global can be used even if the name is given as a string.
go to post Julius Kavay · Jul 15, 2023 As an addition to the above possibilities, you can ALWAYS use (assumed, you have the rights to access the database where the global lives - this is true for both of the above too) extended global access. Just one remark, this kind of access is possible but not the recommended way for creating regular classes (databases) rather to occasionally (on demand) access data from other namespace and/or namespaces. set nsp = "USER" set myvar = ^|nsp|MyGlobal(1,2,3) If there is no namespace associated with the database (where the global lives) just use the implicit namespace set dir = "^^C:\mydatabases\myfolder\" // win-world, "^^pathToTheDatabase" set dir = "^^/opt/mydatabases/myfolder/" // unix-world, write ^|dir|myglobal(1,2,3) // and, of course all other commands and functions kill ^|dir|myglobal(1) write $order(^|dir|myglobal(1,2)) set isDef = $data(^|dir|myglobal)
go to post Julius Kavay · Jul 15, 2023 Indirection is your friend, which of course, works for globals, locals and other things too. set ^myglobal="This is the root node" set ^myglobal(12)="A node on level 1" set ^myglobal(17)="More level 1 node" set ^myglobal(17,1)="Data on the second level" set ^myglobal(19,3)="More data on the second level" ; now start to play indirection set someVariable="^myglobal" // the better way were: set someVariable=$name(^myglobal) ; and get the content of the above global write @someVariable // --> This is the root node write @someVariable@(12) // --> A node on level 1 write @someVariable@(17,1) // --> Data on the second level ; the same as above set myVariable="^myglobal(17)" // Better: set myVariable=$name(^myglobal(17)) write @myVariable // --> More level 1 node write @myVariable@(1) // Data on second level ; a bit overcomplicated set string1="^" set string2="myglobal" write @(string1_string2_"("_(15+4_","_(1+2))_")") // --> More data on second level So just (re)read the docu about indirection...
go to post Julius Kavay · Jul 8, 2023 Somehow I don't understand your problem. If I create a simple class with a %Text property, insert some text data and then query for the word "time" I get it without problem. Class DC.TextData Extends %Persistent { Property Comment As %Text(LANGUAGECLASS = "%Text.English", MAXLEN = 1000); } Now some data and the query USER>d ##class(DC.TextData).%KillExtentData() USER>s tt=##class(DC.TextData).%New(),tt.Comment="Notice, time is money." w tt.%Save() 1 USER>s tt=##class(DC.TextData).%New(),tt.Comment="It's time for a break." w tt.%Save() 1 USER>s tt=##class(DC.TextData).%New(),tt.Comment="There is no business like show business." w tt.%Save() 1 USER>d $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 $zversion 5. select $zversion Expression_1 IRIS for UNIX (Ubuntu Server LTS for x86-64) 2021.2 (Build 649U) Thu Jan 20 2022 08:49:51 EST 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0006s/4/140/0ms execute time(s)/globals/cmds/disk: 0.0008s/0/394/0ms cached query class: %sqlcq.USER.cls7 --------------------------------------------------------------------------- [SQL]USER>>select * from DC.TextData where Comment %CONTAINS('time') 6. select * from DC.TextData where Comment %CONTAINS('time') ID Comment 1 Notice, time is money. 2 It's time for a break. 2 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0005s/4/140/0ms execute time(s)/globals/cmds/disk: 0.0043s/30/4,322/0ms cached query class: %sqlcq.USER.cls2 --------------------------------------------------------------------------- [SQL]USER>>quit USER>
go to post Julius Kavay · Jul 7, 2023 I know exactly nothing about healthcare, healthcare data, healthcare-classes and objects... sorry. For me it's a simple ObjectScript problem, where you try to do something (probably converting a dynamic object to its string representation - the above error message is known to me for this case). Does such a conversion occurs (somewhere) in your code?
go to post Julius Kavay · Jul 7, 2023 The error message <METHOD NOT SUPPORTED> says everything. USER>s obj={"name":"john", "value":65} USER>w obj.%ToJSON() // --> {"name":"john","value":65} USER>s obj={"name":"john", "value":65, "dynObj":{"info":"something"} } USER>w obj.%ToJSON() // --> {"name":"john","value":65,"dynObj":{"info":"something"}} USER>s obj={"name":"john", "value":65, "dynObj":{"info":"something"}, "cosObj":(##class(%Net.HttpRequest).%New()) } USER>w obj.%ToJSON() // --> <METHOD NOT SUPPORTED> *%ToJSON,%Net.HttpRequest So the problem is, you try to "stringify" (JS-speech) a dynamic object, where one of the properties contains a non-dynamic object (%Net.HttpRequest in the above example).
go to post Julius Kavay · Jul 7, 2023 There are no reserved words for %Contains but there is a requirement on the field (property) type. Excuse me for my arrogance, but instead of reading the documentation everybody thinks, it's cheaper to ask a question in the developer community, to get a ready made solution. So please read this first and if something is not clear, then tell it us what you do not understand and we will help you to understand.
go to post Julius Kavay · Jun 30, 2023 I have absolutely nothing to do with health and HL7 etc. except I know, they exists but the $length(string,delimiterstring) function will you always tell, how many subfields a string has for a given delimiter string. write $l("","-") --> 1 write $l("abc-def","-") --> 2 write $l("abc-","-") --> 2 write $l("abc-def-ghi","-") --> 3 etc.
go to post Julius Kavay · Jun 23, 2023 Maybe there are tools to dump a dynamic object, I don't know, but you can always write your own short method /// obj: a dynamic object /// opt: an option, how to display array elements /// 0: just show the index number /// 1: show the parenthesized index /// 2: show index number in a %Get() method /// tag: optional, the name of the <obj> variable /// ClassMethod DumpJSON(obj, opt = 2, tag = "") { set itr=obj.%GetIterator(), arr=obj.%IsA("%DynamicArray") set:tag]"" tag=tag_"." while itr.%GetNext(.key, .val) { set:arr key=$case(opt, 2:"%Get("_key_")", 1:"("_key_")", :key) if $isobject(val), val.%IsA("%DynamicAbstractObject") { do ..DumpJSON(val,opt,tag_key) } else { write tag,key,": ",val,! } } } For ease of use, put it into the %ZLANGC00.mac, for example %ZLANGC00 ; Command extensions // Dump a dymanmic object ZDDUMP(obj,opt,tag) Public { do ##class(your.utility).DumpJSON(obj,.opt,.tag) } For the data, you mentioned above, the following will be displayed set metaDynObj={"versionId":"2","security":[{"system":"http://terminol....} zddump metaDynObj::"metaDynObj" metaDynObj.versionId: 2 metaDynObj.security.%Get(0).system: http://terminology.hl7.org/CodeSystem/v3-Confidentiality metaDynObj.security.%Get(0).code: U metaDynObj.security.%Get(0).display: unrestricted zddump [11,22,33] 0: 11 1: 22 2: 33 zddump [11,22,33]:1:"x" x.(0): 11 x.(1): 22 x.(2): 33