go to post Vitaliy Serdtsev · Feb 27, 2020 Through %ZEN.proxyObject is unlikely to work, since the q parameter cannot be disabled in this case q - output numeric values unquoted even when they come from a non-numeric property Use your own class, for example: Class dc.test Extends %RegisteredObject { Property articlenumber As %String; }s object = ##class(dc.test).%New() s object.articlenumber = "15049950" s x = ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.json,object,,,,"aelotw")Output: { "articlenumber":"15049950" }
go to post Vitaliy Serdtsev · Feb 27, 2020 Hi Evgeny! I can't check for technical reasons. Docker version does not suit me.
go to post Vitaliy Serdtsev · Feb 27, 2020 Conclusion: the quote will be removed from the documentation since it's no longer true. Then besides this, in the documentation for %STARTSWITH need to add the note DEPRECATED and the recommendation "use LIKE 'XXX%'" I also did an analysis for Caché 2018.1 Class del.t Extends %Persistent { Index ip On p; Property p As %VarString; /// d ##class(del.t).Fill() ClassMethod Fill(N = 1000000) { d DISABLE^%NOJRN k ^del.tD,^del.tI f i=1:1:N s ^del.tD(i)=$lb("","test"_i) s ^del.tD=N d ENABLE^%NOJRN d ..%BuildIndices(,,,$$$NO) d $system.SQL.TuneTable($classname(),$$$YES) d $system.OBJ.Compile($classname(),"cu-d") } }Although the plans are exactly the same in SMP the results of the metrics differ: select count(*) from del.t where p like 'test7%' Row count: 1 Performance: 0.291 seconds 333340 global references 2000537 lines executed select count(*) from del.t where p %startswith 'test7' Row count: 1 Performance: 0.215 seconds 333340 global references 1889349 lines executed For the next two queries, the INT code matches: &sql(select * from del.t where p like 'test7%') &sql(select * from del.t where p %startswith 'test7')But for these - is already different, so the metrics in SMP are different: &sql(select * from del.t where p like :a) &sql(select * from del.t where p %startswith :a)In IRIS 2020.1, the work with embedded queries was changed, but I can't check it.
go to post Vitaliy Serdtsev · Feb 26, 2020 Quote from the documentation: For performance reasons, the predicate %STARTSWITH 'abc' is preferable to the equivalent predicate LIKE 'abc%'. proof
go to post Vitaliy Serdtsev · Feb 26, 2020 I think that the author meant that the simplest queries of the form like 'text%' automatically worked as/converted to %startswith 'text'
go to post Vitaliy Serdtsev · Feb 25, 2020 I would look towards modern frameworks like React, Vue, etc., especially considering that CSP/ZEN/Mojo no longer develops.
go to post Vitaliy Serdtsev · Feb 25, 2020 The CSPBIND value is required at the compile-time to generate code on the client and server side. You try to change this value at runtime. See: CSP Page Lifecycle CSP Elements: Expressions
go to post Vitaliy Serdtsev · Feb 25, 2020 See: JSON Representation of a global structure Cogs Library Introducing InterSystems IRIS Document Database (DocDB)
go to post Vitaliy Serdtsev · Feb 24, 2020 If you have old version of Caché, you can use %ZEN.Auxiliary.jsonProvider or %ZEN.Auxiliary.altJSONProvider, which have a bunch of useful methods, for example: %ArrayToJSON %WriteJSONFromArray %WriteJSONStreamFromArray etc. Here are two small examples: set array=##class(%ListOfDataTypes).%New() for i=1:1:4000000 d array.Insert("item"_i) write "count = ",array.Count(),! do ##class(%ZEN.Auxiliary.altJSONProvider).%WriteJSONStreamFromObject(.stream,array,,,1,"aeloq") ; here you can save stream to a file or send it to the clientset meta=$lb("nameA","nameB","nameC") for i=1:1:4000000 set data(i)=$lb("itemA"_i,"itemB"_i,"itemC"_i) do ##class(%ZEN.Auxiliary.altJSONProvider).%ArrayToJSON(.meta,.data)
go to post Vitaliy Serdtsev · Feb 24, 2020 To Dmitry's words I will add a few links from the documentation: write [listname] (Caché List structured data displays in encoded form) List-Structure String Operations In your case, be the $LISTTOSTRING function is useful, for example: USER>set first=$lb("words","more","words") USER>write first words-morewords USER>write $listtostring(first) words,more,words USER>write $listtostring(first,"^") words^more^words USER>write $listtostring(first,"") wordsmorewordsI think that the result of "dogcatfish" in the book was due to copying/pasting, which caused the service characters to be lost. By the way, here on the forum it’s also not so easy to insert this gibberish ;)
go to post Vitaliy Serdtsev · Jan 30, 2020 Are you sure that the "cdate" type is a string ? Maybe %Date or %PosixTime? Even if leave a string, the result is highly dependent on ExtentSize. For example, if ExtentSize=10, the plans match.
go to post Vitaliy Serdtsev · Jan 30, 2020 See Users, Roles, and Privileges. In addition, you can optionally enable auditing.
go to post Vitaliy Serdtsev · Jan 24, 2020 It should be noted that this applies not only to the try/catch block, but also to other blocks, for example: f i=1:1:2 { q 1 ; runtime error, but the line is highlighted } do { q 2 ; compilation error }while(0) while 0 { q 3 ; compilation error }
go to post Vitaliy Serdtsev · Jan 23, 2020 And more food for thought: Class dc.test [ Abstract ] { /// d ##class(dc.test).test() ClassMethod test(N As %Integer = 10) { d ..Run1(N),..Run2(N),..Run3(N),..Run4(N) } ClassMethod Run1(N As %Integer) { f i=1:1:4 { s time(i,"start")=$zh f j=1:1:N { i i=2 { s a=20 } ElseIf i=3 { s a=30 } ElseIf i=1 { s a=10 } Else { s a=-4 } } s time(i,"end")=$zh } w "If i=2: ",?12,time(2,"end")-time(2,"start")," seconds",!, "ElseIf i=3: ",?12,time(3,"end")-time(3,"start")," seconds",!, "ElseIf i=1: ",?12,time(1,"end")-time(1,"start")," seconds",!, "Else: ",?12,time(4,"end")-time(4,"start")," seconds",!! } ClassMethod Run2(N As %Integer) { f i=2,3,1,4 { s time(i,"start")=$zh f j=1:1:N s a=$case(i,1:10,2:20,3:30,:-4) s time(i,"end")=$zh } w "i=1: ",time(1,"end")-time(1,"start")," seconds",!, "i=2: ",time(2,"end")-time(2,"start")," seconds",!, "i=3: ",time(3,"end")-time(3,"start")," seconds",!, "i=4: ",time(4,"end")-time(4,"start")," seconds",!! } ClassMethod Run3(N As %Integer) { f i=1,2,3,4 { s time(i,"start")=$zh f j=1:1:N s a=$case(i,2:20,3:30,1:10,:-4) s time(i,"end")=$zh } w "i=1: ",time(1,"end")-time(1,"start")," seconds",!, "i=2: ",time(2,"end")-time(2,"start")," seconds",!, "i=3: ",time(3,"end")-time(3,"start")," seconds",!, "i=4: ",time(4,"end")-time(4,"start")," seconds",!! } ClassMethod Run4(N As %Integer) [ ProcedureBlock = 0 ] { n i,time,j,a f i=2,3,1,4 { s time(i,"start")=$zh f j=1:1:N d $case(i,1:a1,2:a2,3:a3,:a4) s time(i,"end")=$zh } w "i=1: ",time(1,"end")-time(1,"start")," seconds",!, "i=2: ",time(2,"end")-time(2,"start")," seconds",!, "i=3: ",time(3,"end")-time(3,"start")," seconds",!, "i=4: ",time(4,"end")-time(4,"start")," seconds",!! q a1 s a=10 q a2 s a=20 q a3 s a=30 q a4 s a=-4 q } } USER>d ##class(dc.test).test(1000000) If i=2: .027962 seconds ElseIf i=3: .043612 seconds ElseIf i=1: .073138 seconds Else: .068023 seconds i=1: .035705 seconds i=2: .035941 seconds i=3: .03498 seconds i=4: .033288 seconds i=1: .078231 seconds i=2: .052477 seconds i=3: .066045 seconds i=4: .07372 seconds i=1: .051371 seconds i=2: .052017 seconds i=3: .050972 seconds i=4: .052397 seconds USER>d ##class(dc.test).test(1e6) If i=2: .060933 seconds ElseIf i=3: .071999 seconds ElseIf i=1: .094509 seconds Else: .096684 seconds i=1: .058554 seconds i=2: .058182 seconds i=3: .059299 seconds i=4: .054863 seconds i=1: .09973 seconds i=2: .074734 seconds i=3: .087673 seconds i=4: .097123 seconds i=1: .082372 seconds i=2: .084538 seconds i=3: .081647 seconds i=4: .079353 seconds
go to post Vitaliy Serdtsev · Jan 23, 2020 Hi Peter. Ok. w "Time for If (i=2): ",time(2,"end")-time(2,"start")," seconds",!, "Time for ElseIf #1 (i=3): ",time(3,"end")-time(3,"start")," seconds",!, "Time for ElseIf #2 (i=1): ",time(1,"end")-time(1,"start")," seconds",!, "Time for Else (i=4): ",time(4,"end")-time(4,"start")," seconds",!! 1e6 Time for If (i=2): .030974 seconds Time for ElseIf #1 (i=3): .045126 seconds Time for ElseIf #2 (i=1): .07144 seconds Time for Else (i=4): .087353 seconds 1e9 Time for If (i=2): 28.59286 seconds Time for ElseIf #1 (i=3): 43.044261 seconds Time for ElseIf #2 (i=1): 82.277535 seconds Time for Else (i=4): 69.212718 seconds
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?