go to post Gerd Nachtsheim · Nov 2, 2018 Well, the documentation leaves a lot of room for improvement and you can sure write this into a much shorter version but I wanted to make sure folks get the (somewhat abstract) idea.When your line is $list'ed you can be sure further processing is not affected by delimiters. I also have to say that my solution cannot compete with John (Murray)'s crisp & elegant one-liner.
go to post Gerd Nachtsheim · Nov 2, 2018 You could use CSV() like this... (sorry for the weird formatting)isdDemoCSVToListquitTest() public{set tDescriptor = "ROW(STR VARCHAR,STR2 VARCHAR,STR3 VARCHAR,STR4 VARCHAR, STR5 VARCHAR)"set tLine = "ABC Company,""123 Main St, Ste 102"",""Anytown, DC"",10001,234-567-8901"do CSVToList(tLine,tDescriptor,.tOutput)write !zw tOutput kill tOutput for i=1:1:3{set tLineArray($i(tLineArray)) = """eins"",""deux"",line"_i}do CSVToList(.tLineArray,tDescriptor,.tOutput)write !zw tOutput }CSVToList(&pLines,pDescriptor,&pListArray) public{#dim tRS as %SQL.StatementResultkill tListArrayif ($d(pLines)<10) { set pLines(1)=pLines,pLines=1 }set tTempStream = ##class(%Stream.TmpCharacter).%New()for tIdx = 1 : 1 : pLines{do tTempStream.WriteLine(pLines(tIdx))}do tTempStream.Rewind()set tRS = ##class(%SQL.Statement).%ExecDirect(,"call %SQL_Util.CSV(,?,?)",.pDescriptor,tTempStream).%NextResult()while (tRS.%Next(.tSC)){set tList = ""for tCol = 1 : 1 : tRS.%GetMetadata().columnCount {set tValue = tRS.%GetData(tCol) set tList = tList _ $lb(tValue)} set pListArray($i(pListArray))=tList}quit } Your output then looks like this tOutput=1tOutput(1)=$lb("ABC Company","123 Main St, Ste 102","Anytown, DC","10001","234-567-8901")tOutput=3tOutput(1)=$lb("eins","deux","line1","","")tOutput(2)=$lb("eins","deux","line2","","")tOutput(3)=$lb("eins","deux","line3","","")
go to post Gerd Nachtsheim · Nov 1, 2018 Please, never ever rely on undocumented APIs. They may be taken out or change semantics without further notice. The best you get is "use at your own risk" if you think you have to. There is a plethora of one-liner suggestions here you can use for the same purpose. No need to walk into undocumented InterSystems system code for an LPAD function.
go to post Gerd Nachtsheim · Sep 26, 2018 What is the reaction you expect here? - truncate? - throw an exception? Do you want to precalculate length at runtime - for all of the results - per row - per column - only valid for the caller(i.e. each call has different length limitiations depending on context) ? you sure could do some nasty things at runtime You could pass an extra parameter that has a list of length elements for each column like Query ClientList(pLengthList as %List = { $lb(10,10,50) }) SELECT SUBSTRING(f1,1,$listget(pLengthList,1,50)) as f1, ... A simple sample could look like this /// dynamic length restriction Class User.DynaPar { ClassMethod RunTest(pMax As %Integer = 5) { #dim tSQL as %String #dim tIdx as %Integer #dim tRS as %SQL.StatementResult set tSQL = "SELECT * FROM myQuery()" for tIdx = 1 : 1 : 10 { set tRS = ##class(%SQL.Statement).%ExecDirect(,tSQL) if tRS.%Next() { write !,$j(tIdx,3),": "_tRS.%GetData(1) } } } Query myQuery(pListOfLengths As %List = {..GetLengths()}) As %SQLQuery [ SqlName = MyQuery, SqlProc ] { SELECT TOP 1 SUBSTRING('abcdef',1,$LISTGET(:pListOfLengths,1,1)) } ClassMethod GetLengths() As %List { return $lb(1+$random(6)) } } Does that do what you want?
go to post Gerd Nachtsheim · Aug 15, 2018 I thought this might do the trick but I am not 100% sure... SELECT * FROM PET.ImageStudy_Injection isi INNER JOIN PET.RadioTracer rt ON rt.ID = isi.Injection_RadioTracer INNER JOIN PET.ImageFile if ON if.Study = isi.ImageStudy WHERE rt.TracerName = 'roadrunner'
go to post Gerd Nachtsheim · Jul 3, 2018 You might want to restructure your multiple conditions per $case in a somewhat unusual fashion like this Class User.FunWithCASE { ClassMethod CaseDemo(pNum as %Integer, pBoole as %Boolean = 0, pStr as %String) as %String { return $case(1, /* whatever is true first */ (pNum>100) :"num gt than 100", ((pBoole=1) && (pStr["Green Bay Packers")) : "True Superbowl Champion found!!!!", ((pNum<=2) || ($length(pStr)>40)) : "num lt 2 or a looong string", : ..NestedCase(pNum,pBoole,pStr)) } ClassMethod NestedCase(pNum as %Integer, pBoole as %Boolean = 0, pStr as %String) as %String { return $case(1, /* whatever is true first */ (pBoole=0) : "not true ", (pStr["Miami Dolphins") : "Whatever", ($e(pStr,*-4,*)="kees") : "Mon or Yan found", : "Nothing rhymed in here")_" (nested)" } ClassMethod RunTest() { for tNum=1,2,10,101 { for tBoole = 0,1 { set tList= $lb( "Green Bay Packers", "MiamiDolphins", "New York Yankees", "Maxwell's Silver Hammer", $tr($j(" ",41)," ","*") ) set tPos=0,tStr="" while ($listnext(tList,tPos,tStr)) { write !,"CaseDemo("_tNum_","_$case(tBoole,1:"true",:"false")_","_$$$quote(tStr)_")" ,?40,..CaseDemo(tNum,tBoole,tStr) } } } } }
go to post Gerd Nachtsheim · Dec 27, 2017 Tryselect * from A left join ( B inner join C on B.y = C.y ) on A.x = B.xThat should give you only the Bs that have C match on y
go to post Gerd Nachtsheim · Dec 17, 2017 2017.2 requires Xenial (16.04) and up which come with kernel 4.4 and up.Your Ubuntu versions (precise and trusty) are older and the kernel versions are 3.* instead of 4.*Conclusion is that you might be better off trying to install on a supported version of Ubuntu. HTHGerd
go to post Gerd Nachtsheim · Dec 2, 2017 I fear you will have to give us more information before a helpful advice can be given.what is the table definition?how do the statistics (selectivities) look like?And last not leastwhich SQL do you want to improve and how does the query plan look like?
go to post Gerd Nachtsheim · Dec 1, 2017 I would probably go for some extra hashing safety and add a CRC or something similar to the hash. There may be more subtle hashing methods or combinations thereof that will make duplicates "almost impossible" ;)Class Test.Duplicates Extends %Persistent{Property myText As %String (MAXLEN = 32000);Property myHash as %String (MAXLEN=50)[SqlComputed, Calculated, SqlComputeCode={ set {myHash} = $SYSTEM.Encryption.MD5Hash({myText})_"|"_$ZCRC({myText},7)}, SqlComputeOnChange = (%%INSERT,%%UPDATE,myText) ];/// a bitmap would not be worth the effortIndex ixMyHash on myHash;ClassMethod RunTest(pMax as %Integer = 1000, pDelete as %Boolean = 0){ write !,"begin "_..%ClassName(1) do DISABLE^%SYS.NOJRN() try { &sql(SET TRANSACTION %COMMITMODE NONE) do:pDelete ..%KillExtent() for tIdx = 1 : 1 : pMax { set tRandomStr = ##class(%PopulateUtils).StringMin(100,32000) &sql(INSERT INTO Duplicates(myText) VALUES(:tRandomStr)) continue:SQLCODE'=0 write:(tIdx#100=0) !,tIdx_" records inserted" } &sql(SET TRANSACTION %COMMITMODE IMPLICIT) } catch(tEx) { write !,"Oops..." write !,tEx.DisplayString() } DO ENABLE^%SYS.NOJRN() write !,"end "_..%ClassName(1)}}I don't think that checking for duplicates can be solved other than have a reliable index per hash.Note you can have more subtle hashing (hash sub-pieces, etc.) but you cannot have a reliable hasDuplicate property at runtime that goes beyond the current snapshot of data during INSERT. IOW, it does not mean much in a system with lots of concurrent access.In the end if will be SELECT COUNT(*) AS CountDuplicates FROM Test.Duplicates GROUP BY myHash HAVING COUNT(*) > 1If you want to avoid duplicates you can make the index unique.
go to post Gerd Nachtsheim · Nov 30, 2017 Agree with Robert (how couldn't I? ;) )The crucial questions is how long does it take to copy the index vs. rebuilding it? And, if your index has not been rebuilt for a long time, will a reorganized global be beneficial to your performance? It usually is.Also note that the recent versions of %BuildIndices() exploit multiple cores whenever possible and will run much faster than the older, serialized approach.As Eduard mentioned, functional indices, or indices on collection with handcrafted BuildValueArray() for that matter, may be a different beast and may run for a long time.
go to post Gerd Nachtsheim · Nov 17, 2017 Funny, I learnt a similar approach by the numbers many moons ago.USER>w $tr("12/34/5678",56781234,20171116)11/16/2017
go to post Gerd Nachtsheim · Nov 12, 2017 Tell your trigger that it shall be pulled on SQL + OO events like thisTrigger OnUpdate [ Event = UPDATE, Foreach = row/object ]{[...]}That should to the trick, by default it is SQL only. HTHGerd
go to post Gerd Nachtsheim · Jul 13, 2016 One of the really cool features of SQuirreL is the ability to have multiple different drivers of the same vendor. E.g. if you need to work with drivers from 2010.* to 2016.* you can have different drivers for each connection. In Java, it is a little bit of a challenge to use different versions of the same JDBC driver simultaneously, SQuirreL does that job very conveniently.
go to post Gerd Nachtsheim · Jul 1, 2016 I also would like to understand the dummy number - what does that mean?If you want to use %VID for pagination of large sets you might want to consider working with keysets in a snapshot rather than doing pseudo-windowing with %VID. This can become quite costly if you are enforcing an ordered output,e.g.SELECT * FROM (SELECT ID,Name FROM Sample.Person WHERE Name LIKE ? )WHERE %VID BETWEEN ? AND ?ORDER BY Nameif your dataset is very large this can be quite expensive if you plan to step through this pagewise.