go to post Vitaliy Serdtsev · Jun 15, 2017 The jsonProvider code may also be invoked from a non-Zen context by calling one of the following APIs: %WriteJSONFromArray %WriteJSONFromObject %WriteJSONStreamFromArray %WriteJSONStreamFromObject %ConvertJSONToObject proof Example: d ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%OpenId(1),,,1,"aelqoc") w "<- json = ",stream.Read(),!
go to post Vitaliy Serdtsev · Jun 14, 2017 E.g.: s fileName="C:\temp\test.txt" s f=##class(%FileCharacterStream).%New() s f.Filename=fileName s f1=##class(%FileCharacterStream).%New() s f1.Filename=fileName d f.Write("start ") d f.CopyFrom(f1) d f.Write(" end") d f.SaveStream() s f="",f1=""Result: test.txt (Before): bla-bla-bla test.txt (After): start bla-bla-bla end
go to post Vitaliy Serdtsev · Jun 14, 2017 If you know how to work with ActiveX from MS Excel VBA, then there is no problem. E.g. (demo.vbs): Set f = CreateObject("CacheActiveX.Factory") Set rs = CreateObject("CacheActiveX.ResultSet") If Not f.IsConnected() Then f.Connect("cn_iptcp:127.0.0.1[1972]:SAMPLES:_SYSTEM:SYS") Set rs=f.DynamicSQL("select TOP 3 * from Sample.Person") rs.Execute() while rs.Next WScript.Echo rs.Get("SSN") 'print of field SSN for first three rows from the table Sample.Person wend rs.Close() Set person = f.Static("Sample.Person") age=person.CurrentAge(45678) 'call of method of class Sample.Person WScript.Echo age End IfRunning a Query in Visual Basic
go to post Vitaliy Serdtsev · Jun 9, 2017 If you only need SQL access, then will be easier to create a view (CREATE VIEW), if need both, then - %CacheSQLStorage, e.g.: Class demo.A Extends %Persistent { Property P1; Property P2; ClassMethod Fill() { d ..%KillExtent() f i=1:1:3 { s t=..%New() s t.P1="P1_"_i s t.P2="P2_"_i d t.%Save() } } Storage Default { <Data name="ADefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> <Value name="2"> <Value>P1</Value> </Value> <Value name="3"> <Value>P2</Value> </Value> </Data> <DataLocation>^demo.AD</DataLocation> <DefaultData>ADefaultData</DefaultData> <IdLocation>^demo.AD</IdLocation> <IndexLocation>^demo.AI</IndexLocation> <StreamLocation>^demo.AS</StreamLocation> <Type>%Library.CacheStorage</Type> } } Class demo.B Extends %Persistent [ Final, StorageStrategy = Default ] { Parameter READONLY = 1; Property P2; Storage Default { <SQLMap name="BDefaultData"> <Data name="P2"> <Piece>3</Piece> </Data> <Global>^demo.AD</Global> <RowIdSpec name="1"> <Expression>{L1}</Expression> <Field>ID</Field> </RowIdSpec> <Subscript name="1"> <Expression>{ID}</Expression> </Subscript> <Type>data</Type> </SQLMap> <StreamLocation>^demo.AS</StreamLocation> <Type>%CacheSQLStorage</Type> } }Result: USER>d ##class(demo.A).Fill() USER>d $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: >. Enter q to quit, ? for help. USER>>select * from demo.A 1. select * from demo.A ID P1 P2 1 P1_1 P2_1 2 P1_2 P2_2 3 P1_3 P2_3 3 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.1426s/46110/260143/45ms execute time(s)/globals/lines/disk: 0.0004s/16/809/0ms cached query class: %sqlcq.USER.cls12 --------------------------------------------------------------------------- USER>>select * from demo.B 2. select * from demo.B ID P2 1 P2_1 2 P2_2 3 P2_3 3 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0696s/44550/243602/0ms execute time(s)/globals/lines/disk: 0.0002s/4/619/0ms cached query class: %sqlcq.USER.cls13 --------------------------------------------------------------------------- USER>>quit USER>w ##class(demo.B).%OpenId(3).P2 P2_3
go to post Vitaliy Serdtsev · Jun 7, 2017 Ok, exclusively for fun. I made some improvements and now my score is 9, but if you try very hard, even - 0!Who less ? ;) Here is the code: Class ITPlanet.Task2 [ Abstract ] { Parameter p = {$zwbunpack("㤸㜶㔴㌲")}; ClassMethod main() As %String { q ..#p } } Class ITPlanet.Test [ Abstract ] { ClassMethod length( class = {$classname()}, method = "main") As %Integer [ CodeMode = expression ] { ##class(%Dictionary.MethodDefinition).IDKEYOpen(class, method).Implementation.Size } ClassMethod test(makeDeploy = {$$$NO}) { ;do ##class(ITPlanet.Test).test() set classname="ITPlanet.Task2" set check=9876543210 do:makeDeploy $system.OBJ.MakeClassDeployed(classname) set result=$classmethod(classname,"main") write !,result,!,check, !,"correct: ",$select(result=check:"yes",1:"no"), !,"length: ",..length(classname) } } USER>do ##class(ITPlanet.Test).test() 9876543210 9876543210 correct: yes length: 9 USER>do ##class(ITPlanet.Test).test(1) 9876543210 9876543210 correct: yes length: 0
go to post Vitaliy Serdtsev · Jun 6, 2017 You can use the class %ZEN.proxyObject, e.g.: Class demo.Customer Extends %RegisteredObject { Property p1 As %String; Property p2 As %String; Property list As %Collection.ListOfDT; /// d ##class(demo.Customer).Test() ClassMethod Test() { s customer=##class(demo.Customer).%New() s customer.p1="p1" s customer.p2="p2" s customer.list=##class(%ListOfDataTypes).%New() d customer.list.InsertList($lb(1,"two",,"four")) s appointment=##class(%ZEN.proxyObject).%New() s appointment.a1="a1" s appointment.a2="a2" s appointment.list=##class(%ListOfDataTypes).%New() d appointment.list.InsertList($lb(2,3,"test",8)) ; Cancellation s response=##class(%ZEN.proxyObject).%New() s response.Code="Cancellation" s response.Info="Info_Cancellation" w response.Code,":",! d response.%ToJSON(,"2aelow") d response.%Clear() ; Customer s response.Code="Customer" s response.Info=customer w !!,response.Code,":",! d response.%ToJSON(,"2aelow") d response.%Clear() ; Appointment s response.Code="Appointment" s response.Info=appointment w !!,response.Code,":",! d response.%ToJSON(,"2aelow") } } USER>d ##class(demo.Customer).Test() Cancellation: { "Code":"Cancellation", "Info":"Info_Cancellation" } Customer: { "Code":"Customer", "Info": { "p1":"p1", "p2":"p2", "list":["1","two","","four"] } } Appointment: { "Code":"Appointment", "Info": { "a1":"a1", "a2":"a2", "list":[2,3,"test",8 ] } }
go to post Vitaliy Serdtsev · Jun 2, 2017 The translation was already done: Localization in Caché DBMS
go to post Vitaliy Serdtsev · Jun 2, 2017 See still of the source code for the following methods:##class(%Net.MIMEWriter).EncodeStreamBase64()##class(%Net.SMTP).EncodeStreamBase64()##class(%Atelier.v1.Utils.General).Base64FromStream()##class(%XML.Writer).WriteBase64()
go to post Vitaliy Serdtsev · May 24, 2017 Pass-through if No DDL Mapping is FoundE.g.:CREATE TABLE Person (Name varchar(50), FavoriteColors %Collection.ListOfDT)CREATE TABLE Person (Name varchar(50), FavoriteColors %List)CREATE TABLE Person (Name varchar(50), FavoriteColors %ListOfDataTypes)
go to post Vitaliy Serdtsev · May 17, 2017 Refine your version $zv. Perhaps in older versions there were bugs that were then fixed.Simple test:Class my.children Extends %Persistent{Property p1;Relationship parent As my.parent [ Cardinality = parent, Inverse = children ];Method %OnConstructClone( object As %RegisteredObject, deep As %Boolean = 0, ByRef cloned As %String) As %Status [ Private, ServerOnly = 1 ]{ s i%p1 = object.p1 _ " cloned" q $$$OK}}Class my.parent Extends %Persistent{Property p1;Relationship children As my.children [ Cardinality = children, Inverse = parent ];ClassMethod Fill(){ ;d ##class(my.parent).Fill() d ..%KillExtent() f i = 1:1:3 { s p = ..%New() s p.p1 = "parent["_i_"]" f j = 1:1:2 { s c = ##class(my.children).%New() s c.p1 = $$$FormatText("children[%1,%2]",i,j) d p.children.Insert(c) } d p.%Save() } zw ^my.parentD w !,"_______",!! f i = 1,3 d ..%OpenId(i).%ConstructClone($$$YES).%Save() ; or so - the result is the same ; f i = 1,3 d ..%OpenId(i).%ConstructClone($$$NO).%Save() zw ^my.parentD}Method %OnConstructClone( object As %RegisteredObject, deep As %Boolean = 0, ByRef cloned As %String) As %Status [ Private, ServerOnly = 1 ]{ s i%p1 = object.p1 _ " cloned" q $$$OK}}USER>w $zvCache for Windows (x86-64) 2017.2 (Build 672U) Wed May 10 2017 20:43:42 EDTUSER>d ##class(my.parent).Fill()^my.parentD=3^my.parentD(1)=$lb("","parent[1]")^my.parentD(1,"children",1)=$lb("","children[1,1]")^my.parentD(1,"children",2)=$lb("","children[1,2]")^my.parentD(2)=$lb("","parent[2]")^my.parentD(2,"children",3)=$lb("","children[2,2]")^my.parentD(2,"children",4)=$lb("","children[2,1]")^my.parentD(3)=$lb("","parent[3]")^my.parentD(3,"children",5)=$lb("","children[3,2]")^my.parentD(3,"children",6)=$lb("","children[3,1]") _______ ^my.parentD=5^my.parentD(1)=$lb("","parent[1]")^my.parentD(1,"children",1)=$lb("","children[1,1]")^my.parentD(1,"children",2)=$lb("","children[1,2]")^my.parentD(2)=$lb("","parent[2]")^my.parentD(2,"children",3)=$lb("","children[2,2]")^my.parentD(2,"children",4)=$lb("","children[2,1]")^my.parentD(3)=$lb("","parent[3]")^my.parentD(3,"children",5)=$lb("","children[3,2]")^my.parentD(3,"children",6)=$lb("","children[3,1]")^my.parentD(4)=$lb("","parent[1] cloned")^my.parentD(4,"children",7)=$lb("","children[1,2] cloned")^my.parentD(4,"children",8)=$lb("","children[1,1] cloned")^my.parentD(5)=$lb("","parent[3] cloned")^my.parentD(5,"children",9)=$lb("","children[3,2] cloned")^my.parentD(5,"children",10)=$lb("","children[3,1] cloned")
go to post Vitaliy Serdtsev · Feb 2, 2017 > Can I make a serial class always computed?Yes, of course.Class CS.Serial Extends %SerialObject [ NoExtent ]{Property Year As %Integer;Property Month As %Integer;}Class CS.Persistent Extends %Persistent{Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed, Transient ];ClassMethod dataGetStatic() As %List{ quit $lb(2017,1)}}Output:^CS.PersistentD=1^CS.PersistentD(1)=$lb("")ID data1 $lb(2017,1) 1 Rows(s) Affected
go to post Vitaliy Serdtsev · Feb 2, 2017 It all depends on what you wish to achieve.For example:Class CS.Serial Extends %SerialObject{Property Year As %Integer;Property Month As %Integer;Method %MyGetSerial() As %List [ ServerOnly = 1 ]{ q $lb(i%Year,i%Month)}}Class CS.Persistent Extends %Persistent{/// Property is triggered computedProperty data1 As CS.Serial [ SqlComputeCode = {set {*} = ..dataGetStatic()}, SqlComputed ];/// Property is always computedProperty data2 As %List [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed, Transient ];/// data getter method in SQL contextClassMethod dataGetStatic() As %List{ s s=##class(CS.Serial).%New(), s.Month=1, s.Year=2017 q s.%MyGetSerial() ; or q $lb(2017,1)}}---------select ID,data1,data2,data1_Month,data1_Year from CS.PersistentID data1 data2 data1_Month data1_Year1 2017,1 2017,1 1 20172 2017,1 2017,1 1 20173 2017,1 2017,1 1 2017
go to post Vitaliy Serdtsev · Jan 25, 2017 Try to use high level interface to work with sockets: %IO.Socket, %IO.SocketCommon.Look on %SYSTEM.INetInfo.Connected() [aka $ZUTIL(189)] or you can use tools of OS [for example see source code %SYSTEM.INetInfo.CheckAddressExist()]
go to post Vitaliy Serdtsev · Jan 13, 2017 # 1d ##class(%ListOfDataTypes).BuildValueArray($lfs("a,b,c,d,e,f"),.array)s array(0)=$o(array(""),-1)zw array# 2s list=##class(%ListOfDataTypes).%New()d list.InsertList($lfs("a,b,c,d,e,f"))m array=list.Datas array(0)=list.Count()zw arrayThe Result for both variant:array(0)=6array(1)="a"array(2)="b"array(3)="c"array(4)="d"array(5)="e"array(6)="f"
go to post Vitaliy Serdtsev · Jan 10, 2017 Important: pre-need string to convert to UTF-8 USER>w ##class(%xsd.hexBinary).LogicalToXSD($system.Encryption.SHAHash(512,$zcvt("тестtest","O","UTF8"))) 83B481B1A58FA416F34BFF575F2DCA866C6AB790CF0941BC0F1E7E91D916D22866CB9575C666021B2F8A796B20A484ABB29403853EDEA6173B9A61758060117E USER>w ##class(%xsd.hexBinary).LogicalToXSD($system.Encryption.SHAHash(512,$zcvt("test","O","UTF8"))) EE26B0DD4AF7E749AA1A8EE3C10AE9923F618980772E473F8819A5D4940E0DB27AC185F8A0E1D5F84F88BC887FD67B143732C304CC5FA9AD8E6F57F50028A8FF