go to post Chris Bransden · Apr 12, 2021 Thanks, although I don't think that works for me as one of the other contexts I need to access this LinkedFundsByPerson query are as a select query to to return those 4 columns in the original into a result set, and another context is I use it within a UNION query as suggested here: https://community.intersystems.com/post/possible-merge-two-resultset#com...
go to post Chris Bransden · Apr 12, 2021 Then I get error LITERAL ('CAST') expected, CAST found It's like it's unable to process anything other than literal values as parameters for class queries called within SQL. A shame as I would like to avoid duplicating such queries
go to post Chris Bransden · Apr 12, 2021 I tried with the parameter (or removing it from the query entirely), but no change. Indeed, the error message only refers to the first parameter: LITERAL ('PERSON') expected, IDENTIFIER (Person) found DECLARE QRS CURSOR FOR SELECT ... If I send a literal value ('123') then everything works, but it doesn't seem to want to deal with a column reference, but I don't understand why if it can cope with that fine when I expand out the query? eg SELECT Person.ExternalReferenceFROM QUASAR_KYC_Person.Person PersonWHERE NOT EXISTS ( SELECT Fund.InternalReference,Fund.ShortName,ISNULL(FundClosure.ClosureStatus,'Open') AS ClosureStatus,'P' AS Linktype FROM QUASAR_Core_Client.Client AS Client INNER JOIN QUASAR_KYC_Fund.Fund AS Fund ON Client.Number=Fund.InternalReference LEFT JOIN QUASAR_GDPR_Close_Fund.FundClosure As FundClosure ON Client.Number=FundClosure.ID WHERE Client.ClientMarketIndicator='C' AND Client.Number IN ( SELECT Client FROM QUASAR_KYC_Person.FundLink WHERE Person->InternalReference=Person.ID ) )
go to post Chris Bransden · Apr 12, 2021 Hi, Thanks! I get the same error when doing a WHERE 0< ... CUSTOM_MyQuery is a SELECT statement with a parameter. It seems to work fine if I pass in a value, but now a column reference, but I'm not sure why? What's strange is if I replace the call to CUSTOM_MyQuery with the whole contents of that SELECT statement, with TableA.ID instead of the parameter, it works. My real-world CUSTOM_MyQuery is /// Linked Funds via Person->Fund linkQuery LinkedFundsByPerson(personId As %Library.Integer, RWOOnly As %Library.Boolean) As %Library.SQLQuery(CONTAINID = 0, ROWSPEC = "Number:%Integer, Name:%String, Status:%String, LinkType:%String"){SELECT Fund.InternalReference,Fund.ShortName,ISNULL(FundClosure.ClosureStatus,'Open') AS ClosureStatus,'P' AS LinktypeFROM QUASAR_Core_Client.Client AS ClientINNER JOIN QUASAR_KYC_Fund.Fund AS Fund ON Client.Number=Fund.InternalReferenceLEFT JOIN QUASAR_GDPR_Close_Fund.FundClosure As FundClosure ON Client.Number=FundClosure.IDWHERE Client.ClientMarketIndicator='C'AND Client.Number IN(SELECT ClientFROM QUASAR_KYC_Person.FundLinkWHERE Person->InternalReference=:personId)} (the second parameter isn't used but is there for legacy reasons - doesn't seem to matter if I remove it)
go to post Chris Bransden · Apr 11, 2021 If I use a class query in an EXISTS clause like: SELECT *FROM TableAWHERE EXISTS (SELECT * FROM CUSTOM_MyQuery(TableA.ID)) I get an error of the type: LITERAL ('TABLEA') expected, IDENTIFIER (TABLE) found DECLARE QRS CURSOR FOR ... Is there a way around this? Thanks,Chris
go to post Chris Bransden · Mar 14, 2021 Oh, I see! Yes this is perfect - I can create a simple wrapper query with the UNION between calls to Query1 and Query2, and call that when appropriate. All working here! Thanks so much
go to post Chris Bransden · Mar 12, 2021 Oh I see! But doesn't that leave the same issue I have with disabling the UNION'd second half at run time? The only way I can think of is passing it in as a parameter and have the second WHERE clause including WHERE :doUnion = 1 ...but that will still do the second query, and discard it after the fact, I believe, which is inefficient. It might be possible to do with via a CASE statement or IF ELSE somehow? Not sure...
go to post Chris Bransden · Mar 12, 2021 Yes I can put a UNION within a single Class_Query - that's my current approach (see first post), but the issue I have is disabling the UNION half, either within the SQL statement (inelegant and it appears inefficient, at least the way I tried in my first post), or somehow running two Class_Queries into one ResultSet (with the second being enabled at runtime based on a parameter). The queries are too complex to maintain as strings and concatenate them together that way. They need to remain Class_Queries.
go to post Chris Bransden · Mar 11, 2021 These are both in-class query declarations with parameters, like: Query query1(foo, bar) As %Library.SQLQuery { SELECT .... } So I don't think you can append commands to them in this way?
go to post Chris Bransden · Mar 11, 2021 sorry, i've probably not been clear, but for scenario 'doUnion' I want to run query 1 AND query 2 into the resultset. effectively what would happen if you used union statement. i could create two queries, first with query 1 unioned with 2, and second with just with query 1, but that seems a bit ugly from a maintenance/code duplication perspective.
go to post Chris Bransden · Jul 5, 2018 to be clear i understood the risk perfectly, but it's trivial to replace $ZF(-1) calls with the equivalent $ZF(-100) command. so i elected to just do it rather than spend longer doing analysis into whether a specific instance poses a security risk :) our code base has a lot of MUMPS in it, predating cache.
go to post Chris Bransden · Jul 5, 2018 Null arg is not the same as an empty string arg (""), as usual in COS. yes, but the docs for $ZF(-100) say You can specify a null argument as "" https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls... so I would expect the function to pass this to the current shell as a viable null argument (or maybe not at all) Why did you undertake this task, changing of $zf(-1) to $zf(-100), at all? Do you clearly understand the kind of treat you try to eliminate? we have been specifically instructed by intersystems to do this. $ZF(-1) is deprecated also. I can think of a few ways you could exploit the existing function but I think it's probably not good for me to say them in a public forum :) it's used so infrequently in our code (and mostly legacy stuff) that's easier to just replace them all than work out if we have any specific vulnerabilities.
go to post Chris Bransden · Jul 13, 2017 Hi Again! I'm not sure if this related, but I am seeing strange behaviour when I try and calculate and array property. Eg: Property Amount2 As array Of %Numeric [ SqlComputeCode = { set {*} = ##class(ContainerSize).GetTotalAmount2({%%ID})}, SqlComputed, SqlComputeOnChange = (%%UPDATE, %%INSERT), Transient ]; Even if my method does nothing but quits out with a new Array object: quit ##class(%Collection.ArrayOfDT).%New() When I open an instance: macdocs:MACDEV1>w ##class(MacDocs.SalesMarketing.Quotation.ContainerSize).%OpenId("0||WALK04332||1||20").Amount2 Set ptr=0 While $listnext(serialcol,ptr,item) { Set i%Amount2($list(item))=$lis ^ t(item,2) } <LIST>zAmount2GetSwizzled+5^MacDocs.SalesMarketing.Quotation.ContainerSize.1 macdocs:MACDEV1 2e1>w ##class(MacDocs.SalesMarketing.Quotation.ContainerSize).%OpenId("0||WALK04332||1||20").Amount2 3@%Collection.ArrayOfDT Bizarrely it works the second time?! Perhaps there's a better way of calculating array properties upon object load?
go to post Chris Bransden · Apr 19, 2017 Perfect, thanks! I'd actually already tried this but had some other bug in my code that meant me think it wasn't working - I looked more carefully and figured it out :)