go to post Vitaliy Serdtsev · Jan 23, 2020 I have (2019.1.1CE) this is not confirmed: f i=1:1:4 { s time(i,"start")=$zh f j=1:1:1e6 { i i=2 { s a=2 } ElseIf i=3 { s a=3 } ElseIf i=1 { s a=1 } Else { s a=0 } } s time(i,"end")=$zh } w "Time for If (i=2): ",time(1,"end")-time(1,"start")," seconds",!, "Time for ElseIf #1 (i=3): ",time(2,"end")-time(2,"start")," seconds",!, "Time for ElseIf #2 (i=1): ",time(3,"end")-time(3,"start")," seconds",!, "Time for Else (i=4): ",time(4,"end")-time(4,"start")," seconds",! Time for If (i=2): .109283 seconds Time for ElseIf #1 (i=3): .060785 seconds Time for ElseIf #2 (i=1): .08026 seconds Time for Else (i=4): .109974 seconds
go to post Vitaliy Serdtsev · Jan 23, 2020 Hi Nigel. I hasten to inform you that new classes have been added to IRIS for writing/reading streams in JSON format: %Stream.DynamicBinary, %Stream.DynamicCharacter. Here is a sample code: Class dc.test Extends (%RegisteredObject, %JSON.Adaptor) { Property string As %VarString(%JSONFIELDNAME = "longstring"); Property cs As %Stream.TmpCharacter(%JSONFIELDNAME = "cstream"); /// d ##class(dc.test).test() ClassMethod test() { #define fill(%len,%val) $tr($j("",%len)," ",%val) try{ s tmp=..%New() ; the maximum string length when exporting to JSON depends on the length of the property name s tmp.string=$$$fill($$$MaxLocalLength-($l("longstring")+5),$c(351)) $$$ThrowOnError(tmp.cs.Write($$$fill($$$MaxLocalLength,$c(355)))) $$$ThrowOnError(tmp.cs.Write($$$fill($$$MaxLocalLength,$c(354)))) w "[Export] len(string): ",$l(tmp.string),", len(cs): ",tmp.cs.Size,!! s file=##class(%Stream.FileCharacter).%New() s file.Filename="VeryBigObject.json" $$$ThrowOnError(tmp.%JSONExportToStream(file)) $$$ThrowOnError(file.%Save()) ;------------------ s dobj={}.%FromJSON(file) w "1. [Import %DynamicObject] len(longstring): ",$l(dobj.longstring),", len(cstream): ",dobj.%Get("cstream",,"stream").Size,! s obj1=..%JSONNew(dobj) w "2. [Import %RegisteredObject] len(string): ",$l(obj1.string),", len(cs): ",obj1.cs.Size,! /* The following command will generate an error (tested on IRIS 2019.1.1 CE, Unicode): ERROR: <MAXSTRING> zWrite^%Stream.TmpCharacter.1 To avoid errors, you need to fix the code in the GenImportCharacterStream method (see the patch below) */ s obj2=..%New() $$$ThrowOnError(obj2.%JSONImport(file)) w "3. [Import %RegisteredObject] len(string): ",$l(obj2.string),", len(cs): ",obj2.cs.Size,! }catch(ex) { w "ERROR: ",ex.DisplayString(),! } } /// Get an instance of an JSON enabled class.<br><br> /// /// You may override this method to do custom processing (such as initializing /// the object instance) before returning an instance of this class. /// However, this method should not be called directly from user code.<br> /// Arguments:<br> /// dynamicObject is the dynamic object with thee values to be assigned to the new object.<br> /// containerOref is the containing object instance when called from JSONImport. ClassMethod %JSONNew( dynamicObject As %DynamicObject, containerOref As %RegisteredObject = "") As %RegisteredObject [ GenerateAfter = %JSONGenerate, ServerOnly = 1 ] { #dim r As dc.test=$s($IsObject(containerOref):containerOref,1:..%New()) s r.string=dynamicObject.longstring d r.cs.CopyFrom(dynamicObject.%Get("cstream",,"stream")) q r } } Result: USER>d ##class(dc.test).test() [Export] len(string): 3641129, len(cs): 7282288 1. [Import %DynamicObject] len(longstring): 3641129, len(cstream): 7282288 2. [Import %RegisteredObject] len(string): 3641129, len(cs): 7282288 3. [Import %RegisteredObject] len(string): 3641129, len(cs): 7282288 Patch for 2019.1.1CE: Instead of $$$GENERATE(indent_" Set sc=stream.Write(%JSONObject."_$$$QN($$$jsonfieldname(propertyMap))_") If $$$ISERR(sc) Goto %JSONImportExit") need $$$GENERATE(indent_" Set testInvalidField=0, sc=stream.CopyFrom(%JSONObject.%Get(field,,""stream"")) If $$$ISERR(sc) Goto %JSONImportExit")It is possible that in version 2019.4.x has already fixed everything.
go to post Vitaliy Serdtsev · Jan 22, 2020 Can I safely read any size %GlobalBinaryStream into a %Binary? No. Any string (%Binary, %String, %VarString, etc.) has size limit of 3,6MB PS: if it's not a secret, why do you need to read from a stream to a string?
go to post Vitaliy Serdtsev · Jan 22, 2020 The example below works even in Caché: #include %systemInclude n try{ $$$AddAllRoleTemporaryInTry n $namespace s $namespace="SAMPLES" s person=##class(Sample.Person).%OpenId(1) d ##class(%ZEN.Auxiliary.altJSONProvider).%WriteJSONStreamFromObject(.stream,person,,,$$$YES,"aeloq") w "json (string): ",stream.Read($$$MaxLocalLength),!! d ##class(%ZEN.Auxiliary.altJSONProvider).%ConvertJSONToObject(stream,"Sample.Person",.obj) w "obj.Home.Street: ",obj.Home.Street ; or d $system.OBJ.Dump(obj) }catch(ex){ w "Error ", ex.DisplayString(),! }Result: USER>d ^test json (string): {"Name":"Pascal,Martin F.","SSN":"502-68-5767","DOB":43307,"Home":{"Street":"9347 Franklin Drive","City":"Denver","State":"VA","Zip":66346},"Office":{"Street":"4897 Main Blvd","City":"Miami","State":"MO","Zip":60084},"Spouse":"","FavoriteColors":[],"Age":"60"} obj.Home.Street: 9347 Franklin DriveOr use %JSON.Adaptor: Exporting and Importing
go to post Vitaliy Serdtsev · Jan 20, 2020 See also %MATCHES Example: select * from MyTable where MyFieldName %MATCHES '*[~|`]*'
go to post Vitaliy Serdtsev · Jan 17, 2020 See answer by @Brendan Bannon about TuneTable. Documentation: “Relative cost” is an integer value which is computed from many factors as an abstract number for comparing the efficiency of different execution plans for the same query. This calculation takes into account (among other factors) the complexity of the query, the presence of indices, and the size of the table(s). Relative cost is not useful for comparing two different queries. proof
go to post Vitaliy Serdtsev · Jan 17, 2020 Could you cite the test code for $$select^LVBEPVIS and run it from a VBScript program from Windows Explorer. Also give your $zv (interested primarily in 8-bit or Unicode). My test for the Caché Unicode: LVBEPVIS.MAC:select(n) s PLIST=4 s PLIST(1)="018625110" s PLIST(2)="01862511"_$c(9,233,769) s PLIST(3)="F"_$c(1)_"Female"_$c(1)_"Y" s PLIST(4)=35633 q 1test.vbs:Set AxVisM1 = CreateObject("VISM.VisMCtrl.1") AxVisM1.Server="CN_IPTCP:localhost[1972]:_system:@SYS" AxVisM1.NameSpace="USER" AxVisM1.Execute("s err="""",err=$$select^LVBEPVIS(""018625110"")") WScript.Echo AxVisM1.PLISTResult:
go to post Vitaliy Serdtsev · Jan 16, 2020 Example with one file for Windows: Class dc.test [ Abstract ] { /// d ##class(dc.test).test() ClassMethod test() { s ts=##class(%PosixTime).LogicalToUnixTime(##class(%PosixTime).CurrentUTCTimeStamp()), oldName="C:\Tmp\test", newName=oldName_$$$FormatText("a%1.txt",ts) s f=##class(%Stream.FileBinary).%New() d f.LinkToFile(oldName) s gz=##class(%Stream.FileBinaryGzip).%New() s gz.Filename=newName d gz.CopyFromAndSave(f) d ##class(%File).Delete(oldName) } }
go to post Vitaliy Serdtsev · Jan 16, 2020 I would somehow try to use solutions out of the box, for example %Compiler.COS.Refactor:ChangeClName(). In this class are many other useful methods for refactoring.
go to post Vitaliy Serdtsev · Jan 16, 2020 @Julius Kavay got a point. I will offer two more options: Class ABC.Try { /// d ##class(ABC.Try).PackageExists() ClassMethod PackageExists(package = "ABC") { ; option by Julius Kavay s list=##class(%Dictionary.PackageDefinition).GetPackageList() w ''list.Find($zcvt(package,"U")),! ; option 2 w ##class(%Library.RoutineMgr).Exists($zcvt(package,"U")_".PKG"),! ; option 3 k list d $system.OBJ.GetPackageList(.list,package) w ''$d(list),! } } USER>d ##class(ABC.Try).PackageExists("ab") 0 0 0 USER>d ##class(ABC.Try).PackageExists("abc") 1 1 1UPD: Take another look at the %Dictionary.PackageDefinitionQuery:SubPackage/FlatPackage, %ZEN.Utils:EnumeratePackages
go to post Vitaliy Serdtsev · Jan 15, 2020 In IRIS this property is hidden in contrast to Caché: Caché pvaoref IRIS pvaoref By the way this also doesn't work in IRIS anymore: Is there a way to get [ Internal, Private ] property?
go to post Vitaliy Serdtsev · Jan 14, 2020 You can solve the issue "head-on", namely, to re-convert character stream using %IO.StringStream: Class dc.test [ Abstract ] { ClassMethod test() { s char="тест", bin=$zcvt(char,"O","UTF8") w "dump char:" zzdump char w !!,"dump binary:" zzdump bin w !!,"Char:",?21,$system.Encryption.Base64Encode($system.Encryption.SHAHash(256,char)),!, "Binary:",?21,$system.Encryption.Base64Encode($system.Encryption.SHAHash(256,bin)),!! s cs=##class(%Stream.TmpCharacter).%New() d cs.Write(char) s stream=##class(%IO.StringStream).%New() s stream.CharEncoding="UTF8" ; here should be the encoding of your CSV file d stream.CopyFrom(cs) ; or d stream.CopyFrom(source.Stream) s stream.CharEncoding="Binary" /* Attention! The following code is needed to work around an error in method the SHAHashStream, since it expects "Rewind() As %Status", but class the %IO.StringStream uses "Rewind(Output pSC As %Status)" */ s bs=##class(%Stream.TmpBinary).%New() d bs.CopyFrom(stream) w "Char (stream):",?21,$system.Encryption.Base64Encode($system.Encryption.SHAHashStream(256,cs)),!, "Binary (stream):",?21,$system.Encryption.Base64Encode($system.Encryption.SHAHashStream(256,bs)),!! } }Result: dump char: 0000: 0442 0435 0441 0442 тест dump binary: 0000: D1 82 D0 B5 D1 81 D1 82 Ñ.еÑ.Ñ. Char: 2eEII+27ZRfvbZvK4XNsx7WPDb+82DymPPOAdJ0p1SQ= Binary: 409t7BLE9FmeugePMa6BOUINIbG9LXztfSKwnCB0+0g= Char (stream): 2eEII+27ZRfvbZvK4XNsx7WPDb+82DymPPOAdJ0p1SQ= Binary (stream): 409t7BLE9FmeugePMa6BOUINIbG9LXztfSKwnCB0+0g=
go to post Vitaliy Serdtsev · Jan 13, 2020 Also, I advise you to look at CacheActiveX instead of VisM, which has restrictions on the size of the transmitted data. Here is my old article on this subject: link to machine translation
go to post Vitaliy Serdtsev · Jan 13, 2020 Using PLIST PDELIM COS: #include %systemInclude main() s PLIST=2 s PLIST(1)="line 1" s PLIST(2)="multiline 1"_$$$NL_"multiline 2" q 1DELPHI: procedure TForm1.Button1Click(Sender: TObject); begin VisM.Server:='cn_iptcp:127.0.0.1[1972]:_system:@SYS'; VisM.NameSpace:='USER'; VisM.Execute('$$main^dc'); ListBox.Clear; ListBox.Items.Text:=VisM.PLIST; end; Result: line 1 multiline 1 multiline 2
go to post Vitaliy Serdtsev · Jan 11, 2020 Try change TranslateTable: Class dc.test [ Abstract ] { ClassMethod runtests() { ;d ##class(dc.test).runtests() s data="тест" w "data: ",?15,data,! s cs=##class(%Stream.FileCharacter).%New(), cs.Filename="C:\Temp\test.txt", cs.TranslateTable="UTF8" d cs.Write(data), cs.%Save() s bstream=##class(%Stream.FileBinary).%New() d bstream.LinkToFile(cs.Filename) w "Binary:",?15,$system.Encryption.Base64Encode($system.Encryption.SHAHashStream(256,bstream)),! s cstream=##class(%Stream.FileCharacter).%New() d cstream.LinkToFile(cs.Filename) w "Char:",?15,$system.Encryption.Base64Encode($system.Encryption.SHAHashStream(256,cstream)),!! s cstream.TranslateTable="" ;or RAW, SAME w "Char->Binary:",?15,$system.Encryption.Base64Encode($system.Encryption.SHAHashStream(256,cstream)) } } USER>d ##class(dc.test).runtests() data: тест Binary: 409t7BLE9FmeugePMa6BOUINIbG9LXztfSKwnCB0+0g= Char: 2eEII+27ZRfvbZvK4XNsx7WPDb+82DymPPOAdJ0p1SQ= Char->Binary: 409t7BLE9FmeugePMa6BOUINIbG9LXztfSKwnCB0+0g=
go to post Vitaliy Serdtsev · Nov 6, 2019 $EXTRACTdoc Keep in mind that Characters are counted from 1. , so instead $EXTRACT({LabName},0,3) should be $EXTRACT({LabName},1,3) In this case, it is uncritical, because If the from value is 0 or a negative number, $EXTRACT returns a null string; however, if from is used with to, a from value of 0 or a negative number is treated as a value of 1. But in other cases it can lead to the wrong result.
go to post Vitaliy Serdtsev · Nov 4, 2019 That would work storagetime but not at runtime. It was just a matter of ease of accessing data using SQL. No more than. Who knows, maybe the author just decided to use SQL to identify duplicates? I think runtime hook disallowing duplicate inserts would be better. I agree. But this is a completely different task and is solved in a different way. Like this: Property Actor As list Of packet.Actor(POPSPEC = ".ActorFilter():10") [ Required ]; Method ActorFilter() As %Integer { set actorID=$random(10)+1 for i=1:1:$order(i%Actor(""),-1) return:actorID=$list(i%Actor(i),1) "" quit actorID }The author after all asked about SQL therefore I above and asked to specify that it is necessary actually.
go to post Vitaliy Serdtsev · Nov 4, 2019 There are a couple of comments: Instead of Class packet.Actor Extends (%Persistent, %Populate) { Property Name As %String [ Required ]; Index NameIndex On Name [ Unique ]; Property Age As %Integer (MAXVAL=100, MINVAL=10) [ Required ]; Index AgeIndex On Age [ Unique ]; Property Sex As %String (DISPLAYLIST=",Woman,Man") [ Required ]; }better Class packet.Actor Extends (%Persistent, %Populate) { Index NameIndex On (Name, Age) [ Unique ]; Property Name As %Name [ Required ]; Property Age As %Integer(MAXVAL = 100, MINVAL = 10) [ Required ]; Property Sex As %String(VALUELIST = ",Woman,Man") [ Required ]; }Otherwise it will not be possible to insert two or more persons with the same age. Or do you specifically want it? Property Actor As list of packet.Actor (POPSPEC=".ActorFilter()") [Required]; This code contradicts the documentation (Specifying the POPSPEC Parameter for List Properties): Leave basicspec empty if the property is a list of objects. However, in this case, ActorFilter() should return strictly one ID, not a collection. The data in the Actor property is stored as $lb($lb(ID1),$lb(ID2),..,$lb(IDN)), therefore, to select all records that have ID=6 in this field, you need to perform select * from packet.Movie where $listbuild('6') %inlist Actor It seems to me that in your case it would be easier to do so: Property Actor As list Of packet.Actor(STORAGEDEFAULT = "array") [ Required ]; Then the query will be simplified: select * from packet.Movie_Actor where Actor=6 Or even so select * from packet.Movie where Movie_Actor->Actor=6
go to post Vitaliy Serdtsev · Oct 31, 2019 Hi, Yana! Give the class code, the source data and an example of what you want to get in the end.
go to post Vitaliy Serdtsev · Oct 30, 2019 If we have a lot of votes will consider to add it. Do we still have to vote for this? On-my enough one moreover, that moderators (you and Dmitry) and engineers InterSystems (Eduard, Alexander, Anton, Sergey, Anastasia, Timur, etc.) - Russian-speaking. I have one problem with it - if we introduce Russian Community, will you stop answering questions in English?) I here like writing code more than words. It will depend on who is asking.