go to post Vitaliy Serdtsev · Mar 31, 2021 Try the following: SAMPLES>set sc=$$GetSecurityUserInfo^%SYS.SECURITY($username,.p) SAMPLES>zwrite p p("AccountNeverExpires")=.. p("AutheEnabled")=.. p("ChangePassword")=.. p("Comment")=.. p("CreateDateTime")=.. .. p("FullName")=.. p("Roles")=.. p("PhoneProvider")=.. p("Routine")=.. p("SuperUser")=..
go to post Vitaliy Serdtsev · Mar 4, 2021 The interactive tutorials with exercises built into the documentation helped me a lot in my time: Caché Tutorial Topics Map Caché Tutorials Also included was a database "SAMPLES" (code and data) with examples for every taste. I often used it for performance testing. Note: I give a link to version 2016.2, because since version 2017.1, for some reason, the developers have changed the display styles in the online documentation and removed some information. Local documentation does not have these disadvantages. In addition, in the <cachesys>\dev\ folder there were numerous demos with source code for various programming languages and connection technologies (С++, C#, Java, PHP, Python, ODBC, JDBC, ADO.NET, ActiveX, XEP, etc.): Incomplete content \dev\tutorials\ \dev\tutorials\csp \dev\tutorials\java \dev\tutorials\mv \dev\tutorials\pojo \dev\tutorials\security \dev\tutorials\UnitTestEx \dev\tutorials\webservices \dev\tutorials\zen \dev\Cache\ \dev\Cache\callin \dev\Cache\callout \dev\Cache\cctrlcpp \dev\Cache\cctrlvb \dev\Cache\ctrldemo \dev\Cache\HAcluster \dev\odbc\samples\ \dev\odbc\samples\php \dev\odbc\samples\select \dev\odbc\samples\sqlgateway \dev\python\ \dev\python\samples \dev\python\samples3 \dev\cdirect \dev\cpp\samples \dev\dblib\samples \dev\dotnet\samples \dev\java\samples \dev\mv\samples \dev\node.js\samples \dev\perl\samples
go to post Vitaliy Serdtsev · Jan 12, 2021 N<=9 (59 chr) N>9 (62 chr) Code f n=1:1:n f j=n-1:-1:1,0:1:n w !?j f i=1:1:n-j,i-1:-1:1 w i (59 chr) f n=1:1:n f j=n-1:-1:1,0:1:n w !?j f i=1:1:n-j,i-1:-1:1 w i#10 (62 chr) Who is shorter? ;)
go to post Vitaliy Serdtsev · Nov 27, 2020 Examining an XML Subtree try{ $$$ThrowOnError(##class(%XML.XPATH.Document).CreateFromString("<a><b><c>some content</c></b></a>", .doc)) $$$ThrowOnError(doc.EvaluateExpression("/a", "b", .field)) #dim obj As %XML.XPATH.DOMResult = field.GetAt(1) while obj.Read() { if obj.HasValue { write obj.Path,": ",obj.Value,! } } }catch(ex){ write "Error ", ex.DisplayString(),! } Result: b\c: some content
go to post Vitaliy Serdtsev · Nov 26, 2020 set t={"id":"1","Code": 2} write t.%ToJSON(),! do t.%Set("Code","","null") write t.%ToJSON() %Set
go to post Vitaliy Serdtsev · Nov 24, 2020 Creating Class Documentation PS: Once upon a time (when was Caché) there was a wonderful DOCBOOK database that had the methods you needed. Here's my old (2012 sic!) article on this topic: Extending the built-in documentationRU->EN Here you can read a little more: The DocBook Application DocBookwiki
go to post Vitaliy Serdtsev · Nov 9, 2020 There is another way. If you want any empty strings to always be treated as null/"" instead of "/$c(0), then there is an documented setting (within the scope of namespace), namely: ^%SYS("sql","sys","namespace",<YOUR_NAMESPACE>,"empty string") Here is a small example: Class dc.test Extends %Persistent { Property i As %Integer; Property str As %String; /// do ##class(dc.test).Test() ClassMethod Test() { do ..%KillExtent() try{ do $system.SQL.Purge() set ^%SYS("sql","sys","namespace",$namespace,"empty string")=$c(0) ; '' -> $c(0) do ##class(%SQL.Statement).%ExecDirect(,"insert into dc.test(i,str) values(1,'')") ; null -> "" do ##class(%SQL.Statement).%ExecDirect(,"insert into dc.test(i,str) values(2,null)") do $system.SQL.Purge() set ^%SYS("sql","sys","namespace",$namespace,"empty string")="" ; '' -> "" do ##class(%SQL.Statement).%ExecDirect(,"insert into dc.test(i,str) values(11,'')") ; null -> "" do ##class(%SQL.Statement).%ExecDirect(,"insert into dc.test(i,str) values(22,null)") zwrite ^dc.testD kill ^%SYS("sql","sys","namespace",$namespace,"empty string") } catch(ex){ write ex.DisplayString(),! } } } USER>do ##class(dc.test).Test() ^dc.testD=4 ^dc.testD(1)=$lb("",1,$c(0)) ^dc.testD(2)=$lb("",2,"") ^dc.testD(3)=$lb("",11,"") ^dc.testD(4)=$lb("",22,"")
go to post Vitaliy Serdtsev · Nov 9, 2020 Another option just for the fun: Include %SYS.PTools.Stats Class dc.test [ Abstract ] { ClassMethod setValue(args...) As %Status { quit:args<2 $$$ERROR($$$DataMissing) $$$convertArrayToList(args,list) quit:$listlength(list)'=args $$$ERROR($$$RequiredArgumentMissing) set $list(list,*,*)="", var=##class(%Utility).FormatString(list), $extract(var,1,3)=$name(%sessionData), ##; or $name(%session.Data) @var=args(args) quit $$$OK } /// do ##class(dc.test).Test() ClassMethod Test() { new %sessionData try{ do $system.OBJ.DisplayError(..setValue("key1", "val1")), $system.OBJ.DisplayError(..setValue("key1", "key2", "key3", "key4", "val2")), $system.OBJ.DisplayError(..setValue("key1", "key2", , "key4", "val3")), $system.OBJ.DisplayError(..setValue()) write ! zwrite %sessionData } catch(ex){ write ex.DisplayString(),! } } }
go to post Vitaliy Serdtsev · Oct 8, 2020 Try it with between 1 and 5 on the %VID. Just as slow. I ran your code with new index. count(prop1=2) = 2629833 %VID BETWEEN 1 AND 5 .000293 secs %VID BETWEEN 2629829 AND 2629833 3.63472 secs I can't create an index on every possible filter and order by combination. Waiting for @Kyle.Baxter response.
go to post Vitaliy Serdtsev · Oct 8, 2020 Try adding a new index and don't forget make rebuild index/tunetable/recompile class Index idx On (prop1, prop3) [ Type = bitmap ]; Here yet need the help of @Kyle.Baxter. PS: by the way, check select count(*) from mp.test where prop1=2 to insert the correct values in the code %VID BETWEEN 3000000 AND 30000005 Because of this, is obtained 0 Rows(s) Affected
go to post Vitaliy Serdtsev · Oct 7, 2020 I don't think I quite understand you. That is, you need to: do SELECT * FROM <table> WHERE <difficult condition> ORDER BY <some field> DESC then select a certain data page from the resulting result select * from (step1) where %VID between N1 and N2 If not, provide a ready-made example with data similar to the example by @MARK PONGONIS
go to post Vitaliy Serdtsev · Oct 7, 2020 Source code Class mp.test Extends %Persistent { Property prop1; Property prop2; Property prop3; Index idx3 On (prop3, prop1, prop2) [ Type = bitmap ]; ClassMethod Fill(total = 5000000) { d ..%KillExtent() f i=1:1:total s ^mp.testD(i)=$lb("","name","prop2",$r(30)) s ^mp.testD=total d ..%BuildIndices() } ClassMethod Query() { s N=5 &sql(SELECT count(*) into :count FROM mp.test WHERE prop1='name' AND prop2='prop2' AND prop3>='1' AND prop3<='30') w "count=",count,!! s sql=##class(%SQL.Statement).%New() d sql.%Prepare("SELECT %ID,prop3 FROM mp.test WHERE %ID IN ("_ " SELECT * FROM ("_ " SELECT TOP ALL %ID FROM mp.test WHERE prop1='name' AND prop2='prop2' AND prop3>='1' AND prop3<='30' ORDER BY prop3 DESC"_ " ) WHERE %VID BETWEEN ? AND ?"_ ") ORDER BY prop3 DESC") w "first 5 [1:5]",! s rset=sql.%Execute(1,5) s time=$zh d rset.%Display() w !,$zh-time," secs",!! w $$$FormatText("last 5 [%1:%2]",count-N+1,count),! s rset=sql.%Execute(count-N+1,count) s time=$zh d rset.%Display() w !,$zh-time," secs" } } USER>d ##class(mp.test).Fill(5000000) USER>d ##class(mp.test).Query() count=3833346 first 5 [1:5] ID prop3 3 3 4 3 24 3 30 3 97 3 5 Rows(s) Affected .000328 secs last 5 [3833342:3833346] ID prop3 4999798 1 4999817 1 4999836 1 4999866 1 4999947 1 5 Rows(s) Affected 2.884304 secs PS: for those who put a minus. May I ask why?
go to post Vitaliy Serdtsev · Sep 11, 2020 There is at least one case where this encoding style is acceptable - it is a generator method. Just look at the code generated by &sql() or CSP, for example. No wonder there are two versions for javascript libraries: for the developer and for production (processed by the minimizer).
go to post Vitaliy Serdtsev · Sep 8, 2020 And what if the answer is given, but the author either does not want to accept the answer at all or does not make a more elegant decision? https://community.intersystems.com/post/there-way-defermine-column-jsono... https://community.intersystems.com/post/creating-json-objects-objectscri...
go to post Vitaliy Serdtsev · Aug 5, 2020 My EAV implementation is the same as your Approach 3, so it will work fine even with fully filled 4.000.000 attributes. Since the string has a limit of 3,641,144, approaches with serial and %List are dropped. All other things being equal, everything depends on the specific technical task: speed, support for Objects/SQL, the ability to name each attribute, the number of attributes, and so on.