go to post Vitaliy Serdtsev · Oct 16, 2017 Isn't it easier to use the built function StringMin, especially when its the code does exactly the same thing? USER>w $length(##class(%PopulateUtils).StringMin(100,100)) 100Source code: ClassMethod StringMin( minlen As %Integer = 1, maxlen As %Integer = 1) As %String [ ProcedureBlock = 1 ] { if maxlen '< minlen { set len=$$$PRand(maxlen-minlen+1)+minlen, string="" for i=1:1:len { Set charn=$s($$$PRand(2):$$$PRand(26)+65,1:$$$PRand(26)+97), string=string_$s(charn<123:$c(charn),1:" ") } quit string } else { quit "" } }
go to post Vitaliy Serdtsev · Oct 16, 2017 Class dc.demo Extends %Persistent { Property ChildPrice As %Library.Float; ClassMethod Test() { ;d ##class(dc.demo).Test() d ..%KillExtent() s obj=..%New() s obj.ChildPrice=2.56 d obj.%Save() &sql(select ChildPrice into :ChildPrice from dc.demo where %ID=1) w ChildPrice,! } } My result: USER>d ##class(dc.demo).Test() 2.56What will be the result you have? Also check the settings for the format of the data types in your tool (DbVisualizer, Caché Monitor, WinSQL, SQuirreL SQL, etc.), in which you make a selection.
go to post Vitaliy Serdtsev · Oct 16, 2017 Synchronous and Asynchronous Methods ClientMethod onunloadHandler() [ Language = javascript ] { this.SomeZenMethod(); } ClassMethod SomeZenMethod() As %Status [ ZenMethod ] { // to do some work quit $$$OK } ClientMethod onunloadHandler() [ Language = javascript ] { var old = zenSynchronousMode; zenSynchronousMode = true; this.SomeZenMethod(); zenSynchronousMode = old; } ClassMethod SomeZenMethod() [ ZenMethod ] { // to do some work }
go to post Vitaliy Serdtsev · Oct 9, 2017 The following code has been tested on versions 2015.2 and 2017.2: Class dc.demo Extends %RegisteredObject { Property f1 As %String; Property f2 As %Integer; Property f3 As %ListOfDataTypes; Method GetTarget( ByRef pParms As %String, Output pObj As %RegisteredObject) As %Status { s pObj = ..%New() i $g(pParms(1))="a" { s pObj.f1 = "Peter" s pObj.f2 = 21 }else{ s pObj.f1 = "Bob" s pObj.f2 = 12 s pObj.f3 = ##class(%ListOfDataTypes).%New() d pObj.f3.InsertList($lb("a","b","c")) } q $$$OK } ClassMethod Obj2Json() { ;d ##class(dc.demo).Obj2Json() s parms(1)="a" d ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%New(),"GetTarget",.parms,$$$YES,"aeloq") w "1) ",stream.Read($$$MaxLocalLength),! k parms d ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%New(),"GetTarget",.parms,$$$YES,"aeloq") w "2) ",stream.Read($$$MaxLocalLength),! } ClassMethod Json2Obj() { ;d ##class(dc.demo).Json2Obj() d ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("{""f1"":""Peter"",""f2"":21,""f3"":[]}",$classname(),.obj) w obj.f1," : ",obj.f3.Count(),! d ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("{""f1"":""Bob"",""f2"":12,""f3"":[""a"",""b"",""c""]}",$classname(),.obj) w obj.f1," : ",obj.f3.Count(),! } }Result: USER>d ##class(dc.demo).Obj2Json() 1) {"f1":"Peter","f2":21,"f3":[]} 2) {"f1":"Bob","f2":12,"f3":["a","b","c"]} USER>d ##class(dc.demo).Json2Obj() Peter : 0 Bob : 3
go to post Vitaliy Serdtsev · Oct 9, 2017 Class dc.SomeClass { Parameter SOMENAME = "Name1"; Query SomeQuery(SOMENAME = {..#SOMENAME}) As %SQLQuery { SELECT ID || :SOMENAME || Name FROM Table1 } Query SomeQuery1() As %SQLQuery { #define SOMENAME ##Expression("'"_$parameter("dc.SomeClass","SOMENAME")_"'") SELECT ID || $$$SOMENAME || Name FROM Table1 } Query SomeQuery2() As %SQLQuery { #define SOMENAME ##Expression("'"_##class(dc.SomeClass).#SOMENAME_"'") SELECT ID || $$$SOMENAME || Name FROM Table1 } ClassMethod Test() { ;d ##class(dc.SomeClass).Test() s rs=##class(%ResultSet).%New("dc.SomeClass:SomeQuery") s sc=rs.Execute() i $$$ISERR(sc) { d $System.Status.DisplayError(sc) } else { d rs.%Display() } } }
go to post Vitaliy Serdtsev · Oct 6, 2017 It also can be solved. The behavior of zenPage.launchPopupWindow depends on the setting useSoftModal. Play around with %OnUseSoftModals in the following example: Class dc.demo Extends %ZEN.Component.page { XData Style { <style type="text/css"> .modalGroupCloseButton { background-color: green; filter: alpha(opacity=20); opacity: 0.2; } .modalGroupCloseButtonHover { background-color: green; } </style> } XData CSS3Style { <style type="text/css"> .modalGroupCloseButton { background-color: red; opacity: 0.2; } .modalGroupCloseButtonHover { background-color: red; } </style> } XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen"> <button caption="Show modal" onclick="zenPage.showModal()"/> </page> } ClientMethod showModal() [ Language = javascript ] { if (!this.isPopup) { zenPage.launchPopupWindow(window.location.href,'DEMO MODAL','center=yes,resizable=no,width=320,height=240'); var els=document.body.getElementsByClassName('modalGroupClose'); if (els.length>0) els[0].onclick=zenPage.onhideGroupHandler; } } ClientMethod onhideGroupHandler() [ Language = javascript ] { if (confirm('[1] Are you sure you want to leave?')) { var modalGroup=zenPage.modalStack[zenPage.modalStack.length - 1]; modalGroup.hideGroup(); } } ClientMethod onunloadHandler(e) [ Language = javascript ] { var message = "[2] Are you sure you want to leave?"; if (typeof e == "undefined") { e = window.event; } if (e) { e.returnValue = message; } return message; } /// Return whether the current page should use soft modal divs. /// The default behaviour is to return 1 for the current instance, but users may set the /// ^%ISC.ZEN.useSoftModals global change this system-wide. /// In some cases, it may be worth modifying the value of the flag based on /// the user agent, particularly if users are expected to access the application /// from mobile devices where new windows behave differently. ClassMethod %OnUseSoftModals() As %Boolean [ CodeMode = expression ] { $$$YES } /// This callback method determines lets a page specify level of CSS support is used by this page. /// The default is to return "", which indicates that the built-in ZEN CSS level /// detection is used. A page can override this and return 2 or 3. Method %OnDetermineCSSLevel() As %Integer [ CodeMode = expression ] { 3 } }
go to post Vitaliy Serdtsev · Oct 5, 2017 Yes, checked and it works in IE11 (see screenshot).In addition, you can find in the file zenutils.js the following code: if (zenIsIE && (!(((typeof zenIsHTML5 != 'undefined') && zenIsHTML5) && ((typeof document.documentMode != 'undefined') && document.documentMode==9)))) { <...> window.document.body.onload = function(event) { return zenPageEventHandler('onload',event); } window.document.body.onbeforeunload = function(event) { return zenPageEventHandler('onunload',event); } <...> }Googling "onbeforeunload не работает" or "onbeforeunload javascript not working".
go to post Vitaliy Serdtsev · Oct 5, 2017 Client Side Callback Methods for the Page /// This client event, if present, is fired when the page is unloaded. /// If this method returns a string value, then that is used as the /// return value of the HTML page's onbeforeunload handler (if more than /// one component returns a string, the first one encountered is used). ClientMethod onunloadHandler() [ Language = javascript ] { return 'Are you sure you want to leave?'; }
go to post Vitaliy Serdtsev · Oct 4, 2017 The following query produces zero results: select bar.name from foo join bar on bar.id %INLIST MyBars This is because MyBars is stored as a $lb($lb(id1),$lb(id2),...,$lb(idN)), and you try to query the data stored in the form $lb(id1,id2,...,idN). Your query need some change to make it work, namely: select name from foo join bar b on $listbuild(b.%ID) %INLIST MyBars
go to post Vitaliy Serdtsev · Oct 2, 2017 For passing array by reference try to use the class $system.WorkMgr instead of job. Sample: Class demo.test [ Abstract ] { ClassMethod Test(array) As %Status { k ^CacheTempUser.dbg m ^CacheTempUser.dbg($zp)=array s ^CacheTempUser.dbg($zp,"$j")=$j q $$$OK } } demo() n queue,arr s arr(1)="qwe" s arr(2)="asd" w "$j = ",$j,! s queue=$system.WorkMgr.Initialize("/multicompile=1",,1) d queue.Queue("##class(demo.test).Test",.arr) d queue.WaitForComplete() zw ^CacheTempUser.dbg qResult: USER>d ^demo $j = 7600 ^CacheTempUser.dbg(8488,1)="qwe" ^CacheTempUser.dbg(8488,2)="asd" ^CacheTempUser.dbg(8488,"$j")=8348
go to post Vitaliy Serdtsev · Sep 21, 2017 w "$ZTZ=",$ztz,! #define 2utc(%t) $tr($zdt($zdt($zdth($system.SQL.TOTIMESTAMP(%t,"YYYYMMDDHHMISS"),3),-3),8,1)," :") s t="20160105125915" w "Winter time: ",t," -> ",$$$2utc(t),! s t="20160705125915" w "Summer time: ",t," -> ",$$$2utc(t)Result (GMT+02:00, Chisinau): USER>d ^test $ZTZ=-120 Winter time: 20160105125915 -> 20160105105915 Summer time: 20160705125915 -> 20160705095915Note: Takes into account summer/winter time Is taken into account to option of OS for automatic daylight saving time For example, if in the OS to disable automatic daylight saving time, the result will be different: USER>d ^test $ZTZ=-120 Winter time: 20160105125915 -> 20160105105915 Summer time: 20160705125915 -> 20160705105915
go to post Vitaliy Serdtsev · Sep 19, 2017 Import data programmatically: %SQL.ExImData CSV() There a sample of the code is brought.
go to post Vitaliy Serdtsev · Sep 15, 2017 In addition to the above. Fill the array tArray can be charged a method %ListOfDataTypes:BuildValueArray(). But I still prefer the next option (unless you count every tick of CPU :) ): s list=##class(%ListOfDataTypes).%New() d list.InsertList(tInputList) ; method #1 s key="" d {s value=list.GetPrevious(.key)} while (key'="") ; method #2 (better way) f key=list.Size:-1:1 s value=list.GetAt(key)
go to post Vitaliy Serdtsev · Jul 25, 2017 You can fix this error directly now, if you don't want to wait for the release of version 2018.1.1. To do this, follow these steps: make export the locale "deuw" %SYS>s Locales("deuw")="" d $system.OBJ.DisplayError(##class(Config.NLS.Locales).ExportList("loc_deuw.xml",.t,.Locales)) zw Locales,t fix the file loc_deuw.xml (by default located in the folder %CACHEHOME%\Mgr) Name of subtable (Where to insert) New lines (That to insert) Add the following lines to the appropriate subtables: COL-German3-Unicode <FromToItem FromToKey="55,55,1">83,83;</FromToItem> <FromToItem FromToKey="55,55,2">7838;</FromToItem> <FromToItem FromToKey="55,55,3">83,7838;</FromToItem> COL-Unicode-German3 <FromToItem FromToKey="7838">55,55;2</FromToItem> <FromToItem FromToKey="83,83">55,55;1</FromToItem> <FromToItem FromToKey="83,7838">55,55;3</FromToItem> LowerCase-Unicode-Unicode <FromToItem FromToKey="7838">223</FromToItem> UpperCase-Unicode-Unicode <FromToItem FromToKey="223">7838</FromToItem> import fixed loc_deuw.xml: %SYS>d $system.OBJ.DisplayError(##class(Config.NLS.Locales).ImportAll("loc_deuw.xml",.t,1+2+4)) zw t %SYS>d $system.OBJ.DisplayError(##class(Config.NLS.Locales).Compile("deuw")) %SYS>d Locale^NLSLOAD("deuw")Just in case, restart Caché. Now, run a small test #include %systemInclude #include %occErrors #include %syNLS test() public { #dim ex As %Exception.AbstractException try { $$$AddAllRoleTemporaryInTry n $namespace s $namespace="%SYS" s oldLocale=$$$LOCALENAME w "Old locale = ",oldLocale,! d ##class(Config.NLS.Locales).Install("deuw") w "Current locale = ",$$$LOCALENAME,!! k ^||low,^||up f w="wei"_$c(223)_"er","weiter","weiser" { s ^||low($zcvt(w,"L"))=1 s ^||up($zcvt(w,"U"))=1 } zw ^||low,^||up s low=$c(223) s up=$zcvt(low,"U") zw low,up zzdump low,up }catch(ex) { w "Error ", ex.DisplayString(),! } d ##class(Config.NLS.Locales).Install(oldLocale) }My result: USER>d ^test Old locale = rusw Current locale = deuw ^||low("weiser")=1 ^||low("weißer")=1 ^||low("weiter")=1 ^||up("WEISER")=1 ^||up("WEIẞER")=1 ^||up("WEITER")=1 low="ß" up="ẞ" 0000: DF ß 0000: 1E9E ẞ
go to post Vitaliy Serdtsev · Jul 25, 2017 Try this: Property Amounts As %ArrayOfDataTypes [ SqlComputeCode = { set {*} = ##class(ContainerSize).GetTotalAmounts({ID})}, SqlComputed, Transient ]; ClassMethod GetTotalAmounts(thisID) As %List { quit $lb( $lb("GBP",1.23), $lb("EUR",2.45) ) }
go to post Vitaliy Serdtsev · Jul 21, 2017 Then try to use a newer JDBC driver (eg from 2017.1). It usually backwards compatible with older versions. If this does not help, then there is only upgrade of Caché.
go to post Vitaliy Serdtsev · Jul 20, 2017 There is a method $system.Memory.Clean(<cleancache>, <defragment>), but unfortunately it appeared only with version 2011.1. Try this code (consider that LONGVARCHAR = %Stream.GlobalCharacter) Read a CLOB through JDBC: try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); Statement st = dbconn.createStatement(); ResultSet rs = st.executeQuery("Select ID,Text from eprinstance.isegment"); while (rs.next()) { int len; Reader reader = rs.getCharacterStream("Text"); while ((len = reader.read()) != -1) bos.write(len); System.out.println(bos); reader.close(); bos.reset(); } bos.close(); st.close(); rs.close(); System.out.println("OK!"); } finally { dbconn.close(); }
go to post Vitaliy Serdtsev · Jul 18, 2017 I didn't know that Caché allowed to use JOINs without specifying FROM. JOIN or SELECTOptional FROM Clause? But it should be noted that for JOIN not all usages are supported, for example: Supported: SELECT * FROM (select 'aaa' Column1,'bbb' Column2 union select 'ccc','ccc' union select 'xxx','yyy' union select 'hhh','zzz') Table1 LEFT OUTER JOIN (select 'ggg' Column1,'hhh' Column3 union select 'xxx','zzz') Table2 ON Table1.Column1=Table2.Column3 Not supported: SELECT * FROM (select 'aaa' Column1,'bbb' Column2 union select 'ccc','ccc' union select 'xxx','yyy' union select 'hhh','zzz') Table1 INNER JOIN (select 'ggg' Column1,'hhh' Column3 union select 'xxx','zzz') Table2 USING (Column1)