go to post Eduard Lebedyuk · Oct 4, 2016 If you are on windows you may have access problems while writing into the root of system drive. I suggest you: Provide filename pointing to your desktop directory (C:\Users\eduard\Desktop\1.xls for me, for example)Instead of w ##class... save the status and decode it into a more readable form: set sc = ##class(Utils.XLS).generateFileFromSQL(...) write $System.Status.GetErrorText(sc)
go to post Eduard Lebedyuk · Oct 4, 2016 I think compile should be called once after the loop. While in the loop you can build a local array of affected classes and pass it to the compiler after the loop.
go to post Eduard Lebedyuk · Sep 27, 2016 You can expose this method to SQL as an SQL stored procedure.
go to post Eduard Lebedyuk · Sep 27, 2016 We have a google calendar (and map) integration for Caché as a part of System of training courses grant project. Check out Stc.Google package there, especially Stc.Google.Calendar class.
go to post Eduard Lebedyuk · Sep 27, 2016 Yes. You can use cursors for that. In the following example rowlist contains list of affected ids. You can get it all at the end or get individual ids right before or after the update, or even decide on the update based on id/val values: Class User.NewClass1 Extends %Persistent { Property val; /// do ##class(User.NewClass1).Test() ClassMethod Test() { do ..%KillExtent() &sql(INSERT INTO NewClass1 SET val = 0) &sql(INSERT INTO NewClass1 SET val = 3) set rowlist = "" &sql(DECLARE NewClass1 CURSOR FOR SELECT %ID,val INTO :id, :val FROM NewClass1) &sql(OPEN NewClass1) for { &sql(FETCH NewClass1) quit:SQLCODE'=0 set val2 = val*2 write "Processing id: ", id,! set rowlist = rowlist _ $lb(id) &sql(UPDATE NewClass1 SET val = :val2 WHERE CURRENT OF NewClass1) } &sql(CLOSE NewClass1) zw rowlist } } It would output in a terminal: >do ##class(User.NewClass1).Test() Processing id: 1 Processing id: 2 rowlist=$lb("1","2") Documentation: WHERE CURRENT OFSQL Cursors
go to post Eduard Lebedyuk · Sep 27, 2016 Here's an example: Class User.NewClass1 Extends %Persistent { Property streams As list Of %Stream.GlobalCharacter; ClassMethod Test() { do ..%KillExtent() set obj = ..%New() set stream1 = ##class(%Stream.GlobalCharacter).%New() do stream1.WriteLine("Hi") set stream2 = ##class(%Stream.GlobalCharacter).%New() do stream2.WriteLine(123) do obj.streams.Insert(stream1) do obj.streams.Insert(stream2) write $System.Status.GetErrorText(obj.%Save()) kill set obj = ..%OpenId(1) for i=1:1:obj.streams.Count() { write "Stream #", i, ": ", obj.streams.GetAt(i).Read($$$MaxCacheInt) } } }
go to post Eduard Lebedyuk · Sep 23, 2016 This method links stream object to an existing file: Method imagefile() { set obj = ##class(Sam.binary).%New() read "enter path to image: ",img set st = obj.Image.LinkToFile(img) write $System.Status.GetErrorText(st) set st = obj.%Save() }
go to post Eduard Lebedyuk · Sep 21, 2016 1. Define your collection property like this: Class collect.arraylist Extends %Persistent { Property DOB As Array of %Date; } Instead of "Array" you can also use "List". Documentation.
go to post Eduard Lebedyuk · Sep 21, 2016 Great article, however, I strongly disagree on the testing tools choice. Curl is not really the option, as CLI tools are really not the best for json editing. Upon the rest of your testing suggestions, I think there are better alternatives, such as:REST clients: “Advanced REST Client” for Chrome and “REST Client” for Firefox, some are also available as a standalone applicationsDebugging web proxies: Charles, Filddler etc. for the rare cases where REST clients do not offer enough information
go to post Eduard Lebedyuk · Sep 21, 2016 For each can be implemented via macros: #define ForEach(%in,%gn) s gn%in=$na(%gn) s %in="" f { s %in=$o(@gn%in@(%in)) q:%in="" #define EndFor } $$$ForEach(key, "^global") Write key,! $$$EndFor
go to post Eduard Lebedyuk · Sep 20, 2016 Ensemble settings can be specified for a namespace. So you specify common setting values (or defaults) in production class, and in a SMP you define the instance-specific settings.