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)
go to post Vitaliy Serdtsev · Jul 18, 2017 Non-optimal plan does not necessarily mean low speed. I have had cases where the query with the best plan to work longer than a query with worse plan. Now the optimizer is pretty advanced. Important to periodically make tuning table and add an index on each field involved in the search. When unknown parameters >5, is easier to do one query than to write a bunch of code.
go to post Vitaliy Serdtsev · Jul 18, 2017 Possible do on-other, namely to write one "universal" query: select * from person where (lastname=:lastname or :lastname is null) and (age > :age or :age is null) That is: sql = "select * from person where (lastname=? or ? is null) and (age > ? or ? is null)" resultset = statement.%Execute(param1, param1, param2, param2)
go to post Vitaliy Serdtsev · Jul 18, 2017 The solution with ##class(%xsd.hexBinary).LogicalToXSD works, but be careful, it only works when all characters in the string have codes <256. All right, because the function works with an array of bytes (binary). Therefore pre-to need lead N-byte string to single-byte string and only then do the conversion, for example: f trantable="SAME","UTF8" { w "-------",!,trantable,! s xN="π=3.14159..." zzdump xN w ! s x1=$zcvt(xN,"O",trantable) zzdump x1 w !! s hex=##class(%xsd.hexBinary).LogicalToXSD(x1) zw hex w $zcvt(##class(%xsd.hexBinary).XSDToLogical(hex),"I",trantable),!! } USER>d ^test ------- SAME 0000: 03C0 003D 0033 002E 0031 0034 0031 0035 π=3.1415 0008: 0039 002E 002E 002E 9... 0000: C0 03 3D 00 33 00 2E 00 31 00 34 00 31 00 35 00 À.=.3...1.4.1.5. 0010: 39 00 2E 00 2E 00 2E 00 9....... hex="C0033D0033002E00310034003100350039002E002E002E00" π=3.14159... ------- UTF8 0000: 03C0 003D 0033 002E 0031 0034 0031 0035 π=3.1415 0008: 0039 002E 002E 002E 9... 0000: CF 80 3D 33 2E 31 34 31 35 39 2E 2E 2E Ï.=3.14159... hex="CF803D332E31343135392E2E2E" π=3.14159...
go to post Vitaliy Serdtsev · Jul 14, 2017 s l=$lb("",,,,,"",,,"BOOLEAN","0",2,2,"1",,"bla",$lb(,,"bla","20050502123400"),"",1,"bla",,0) s jsonStr=[(l)].%ToJSON() w jsonStr,!! s obj=[].%FromJSON(jsonStr) s list=obj."0" zw list Result: ["\u0002\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0001\u0001\t\u0001BOOLEAN\u0003\u00010\u0003\u0004\u0002\u0003\u0004\u0002\u0003\u00011\u0001\u0005\u0001bla\u0019\u0001\u0001\u0001\u0005\u0001bla\u0010\u000120050502123400\u0002\u0001\u0003\u0004\u0001\u0005\u0001bla\u0001\u0002\u0004"] list=$lb("",,,,,"",,,"BOOLEAN","0",2,2,"1",,"bla",$lb(,,"bla","20050502123400"),"",1,"bla",,0)
go to post Vitaliy Serdtsev · Jul 13, 2017 Hi Uri. In my opinion, this possible hear only empirically through load testing on specific hardware. It is also important and the interface between Caché and the world .NET, namely the number of calls made to a DLLBetter performance. Sometimes the performance gain is observed when .NET refers to Caché (ADO.NET, eXTreme .NET Provider), and not vice versa (.NET Gateway). But it always requires a revision of the architecture. By the way, for .NET Provider/ADO.NET there is Connection Pooling
go to post Vitaliy Serdtsev · Jul 13, 2017 Personally, I prefer to use all out of the box, so as not to produce zoo libraries/technologies/languages, etc. Really, both operations possible to execute at a time, for instance so: w $$$FormatText("Create a signature and convert it to base64 (%1)",file64),! s cmd=$$$FormatText("openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -sign %1 %2 | openssl base64 -out %3 -nopad",fileKey,fileMsg,file64) w cmd,!! d $zf(-1,cmd)
go to post Vitaliy Serdtsev · Jul 13, 2017 In addition to said by Eduard: OpenSSL and error in reading openssl.conf file