No, it's just how I'm copying code into here... Here is what I am using:

^llctemp("query")="SELECT * FROM MyTable  WHERE  ((DateTime >= '2017-07-11 00:00:00') AND (DateTime <= '2017-07-18 23:59:59')) AND (Claim->Status->Name IN ('Paid')) AND (Claim->ClaimNumber = ANY (Select Claim->ClaimNumber from MyTable where Claim->ClaimNumber %INLIST ? SIZE ((10)) )) "


                   "returnParams")=1
^llctemp("returnParams",1)=$lb("2902700","2869840","2870820","")

 

That's my test data.  Then I say:

Set status = tRS.Execute(filterParams...)  // < -- look, I need the ... !!

 

Turns out I LITERALLY need the ...  ( ! )

Now I'm not getting the <LIST> but I'm also not getting data!  Sigh.  I'll get it.  I am rushing a little, so that's messing me up.  I think with all this, I can get it to work at some point.  Thanks!!
  

No, I am using %INLIST -- it's all the other where clauses that are using IN, with concatenation. I had read that %INLIST would use the same cached query, or something, so decided %INLIST was better, then ran into this problem where I now have to pass in an Execute parameter, whereas all of the other params are basically hard-coded.  

 

Here's a copy of my query that was built:

SELECT * FROM MyTable  

WHERE  ((DateTime >= '2017-07-11 00:00:00') AND (DateTime <= '2017-07-18 23:59:59')) AND (Claim->Status->Name IN ('Paid'))

AND (Claim->ClaimNumber = ANY (Select Claim->ClaimNumber from MyTable where Claim->ClaimNumber %INLIST ? SIZE ((10)) ))

 

The last line is mine.  Shoot.  It was working when I passed in a $lb like this:

set filter = $listfromstring(filterClaims)   //build my $lb() for the Execute parameter
set returnParams = $lb(filter)  //$lb($lb(1,2,3), hypothetical param2, ... ,paramN)

set param1 = $lg(returnParams,1)   //param1 = $lb(1,2,3)
// ... set paramN = $lg(filterParams,n) ...

Set status = tRS.Execute(param1)

 

but now, with the returnParams as an arity (that's cool, btw),  I'm getting a <LIST>.  If necessary, I'll go back to the forced "param1" thing, because this is an urgent fix.  I can play around with it later.

Yes, exactly.  We are building the sql statement line by line; the where clauses are built based on user input, and the whole mess is concatenated with actual values.  hmm.  But essentially, it looks like the params array is what I needed.  Except that I'm getting a <LIST> error, so I have to go back and look at that.  I'm on 2014.1.3.

 

Thanks!

Oh no, good to know about concatening values instead of using ? Execute params.  I should go rewrite the entire query!  It has so many optional parameters though, so I'll go look at the Rubens/Timothy solution.  Thanks.

 

So this is not a good way to build the where clause:

" Set where(16)=InstancePrefix_"PayerName IN ("_valuelist_")""

 

?

I think it's a bit safer anyway to know exactly how many parameters to expect (avoid a sql injection attack?); I can see how long the one statement with a known number of parameters takes compared to other statements.  So far I have just the one unknown parameter, and all the rest are built into the sql.  Thanks.

Oh -- the parameter is a $lb(); the sql is using %INLIST, which, in the example in the documentation, seems to require a parameter passed in the %Execute() rather than built into a value in the sql statement.  The user might or might not search on this field.  It's more like:

select * from person where ID %INLIST ?

I was thinking that since I need to pass this in to the Execute, I might as well set up a structure in case we add more parameters to the statement in the future; but perhaps it's better to just pass in a known number.

Thanks.

Yes, I needed the SqlComputeOnChange = property;  now it's getting updated for every insert/update when the {property} changes, which is great.  The only problem is, my object is not limited to one row.  It's an object with dynamic properties, where one object is several rows, and one row is the Category and Value of one property.

 

This is fine when I insert or update ALL the rows for one object, but not when I update just one row.  I can't think of a good way to force update on %READERLIST  for other rows, based on a WHERE clause, maybe.

ROWLEVELSECURITY = 1;

///Updated for each row when the property 'Value' changes

Property %READERLIST As %String [ SqlComputeCode = {set {*} = ##class(Users).%SecurityPolicy()}, SqlComputed, SqlComputeOnChange = Value ];

Here's an example of my data:

ID     %READERLIST     Category     Value     Username

1      DEV              Color       Blue      Laura

2      DEV              Number      555       Laura

3      QA               Color       Pink      Jane

4      QA               Number      87        Jane

 

I'll be mulling this over for a while, but would love any other ideas.

Thanks,

Laura

Huh.  I have been unable to have my class update %READERLIST and the %RLI index when I update a row.  It's set when I create/save an object, but it's not updated when I update the object.  Can I show you some simple test classes?

My %READERLIST is based on a role name.

 

From OVERRIDEing the Parameter ROWLEVELSECURITY:

"

/// ROWLEVELSECURITY = 1 | &lt;property&gt; means that row level security is active and the list
/// of users/roles for a given instance/row is contained in a generated property. If
/// the value of this parameter is a valid property name then that property will be
/// used as the reader list and only generated if not already defined.

ROWLEVELSECURITY = 1;

"

?

That's it!  Thank you!  You might have been thinking "it's so obvious", but I wasn't thinking of adding the attributes via html, just for that cell.  I was only thinking of "write", or using the column object to set its cellTitle property, which is not feasible since I can't get the column obejct.  But substituting html works great.  Thanks!

I was able to change the style just for cells whose columns are greater than pSeed (nice touch there), and I removed the showValueInToolTip for the rest of the cells.  I'm sure that would have been noticed at some point.

Laura

I could try that... but this is for the user-friendly page, and I don't want that info on it.  I was hoping to log the info in the error trap.

I just tested the error trap, and found that you can, actually, load the details of an object, while still in the error traap ^%ER.  I had no idea:

Error: 7
 
 7. <UNDEFINED> --routine name -- *undef : CSP Error  at  9:41 am.   $I=|TCP|1972|16772   ($X=327  $Y=14056)                                                                                                                       $J=16772  $ZA=24576   $ZB=$c(0)   $ZS=262144 ($S=267019816)
              set x=undef //LLC testing
 
Variable: %request (copying data ... done)
(base stack level = 20)
          %request =     <OBJECT REFERENCE>[1@%CSP.Request]
Show object details? yes
+----------------- general information ---------------
|      oref value: 1
|      class name: %CSP.Request
| reference count: 6

... etc

So, as long as the error trap has that info available, I'm pretty good.  Does that change in 2016?  Why is the %CSP.ErrorLog page in 2016 so careful to save off the request, session, and response objects inthe error log?

Thanks,

Laura

Can this be used in the System/Security Management/System-side Security Paramters "password pattern" at all?  I'm trying to find a way to match a user's password to something much more restrictive than "8 to 32 alpha, upper, lower, numeric, OR punctuation". I'd like to require at least one of a few kinds of characters (1 upper, 1 punctuation).  

 

I have a nice regex for this, but I'm not sure if I can use a regex, or this cool datatype, in the above mentioned System setting.  Any recommendations?

John, thanks for the response. I might ask this explicitly in the DC later, but I'll have to look at my notes before I do, as I'm sure I'll get some flak.  Just for informational purposes: we were instructed to restrict our users to a  single tab in our web application.  I know this is not how a web application is supposed to work (according to many users on google groups writing about this sort of thing), but the directive came from above.  I wrote simple logic to check if a user has a session already, and if so, he can't open a second tab. Sometimes, due to a bug, or timeouts on queries, the logic thinks the user has a second session when he does not.   At that point the user can't even log into the application. It's at this point that he'll have to call IT, who will have to call a developer, who can then kill his sessions manually from the management portal.  I was trying to give the users a way to "reset" or "clear" their own sessions (logging in first to a separate page perhaps) so that they can use the application again.  When I first began to look at this, I realized that most of this has to be done in the %SYS namespace; hence the problem, and its relavance to this question about changing their own password.

 

However, it hasn't been an issue (yet), so it's on my back burner. When it becomes an issue I'm sure I'll be back asing about it.

 

As always, thanks for the help.

Laura

Well, that helps.  Thanks.  I can't forsee any reason to make it more complicated, unless there is some huge benefit that I'm overlooking? Ah, I was thinking of changing the emails to a list of users, and getting their emails from the user table, so maybe that's a future benefit.

I extended the %Net.MailMessage for one object, and had such a pain of a time stuffing the To prooperty and retrieving it again (it's a list of %String). This time I was thinking a simple %String would be nice, as long as I can use it with SQL, and stuff.

Thanks,

Laura

Hi All, Thanks for the help.  I learned a lot, and looked at our actual instances with a more critical eye.  I'll be recommending some changes on them.  I had installed the unlicensed version of 2016 on my computer just for fun, so there were no license issues (but that's something to keep in mind for our other instances).  I had installed 2016 with minimal security, then tried to increase the security to match our development instance.  That was actually successful; it was the disabling of all the other users that messed it up.

Thanks,

Laura

Ah, thank you.  While playing around with ^SECURITY, I had enabled all users EXCEPT UnknownUser (of course), and after checking out the auditing area of ^SECURITY (thanks for that tip), I saw that it was indeed UnknownUser that is trying to log into the management portal.

 

I did not know about that step, that the CSP gateway has to log in first to serve up a page.  What user is normally used for this?

 

Thanks,

Laura