Danny Wijnschenk · Jul 9, 2024 go to post

Any idea how to hide these health check logs in the audit events, so only 'real' login failure attempts are shown ?

Danny Wijnschenk · Feb 17, 2024 go to post

You can use the spool device : 

Set a(100)="test"
Set a(100,100)="encore"
Open 2 Use 2 zwrite a Close 2
The global ^SPOOL will contain the contents of the zwrite
Danny Wijnschenk · Jan 17, 2024 go to post

In a simple configuration, one namespace uses one database.
But often, a namespace is a combination of a code database(=Routines), a data database (=Globals), and a bunch of mappings to other databases.

Looking at the names of your databases, it could well be the case that you need e.g. a namespace MYDATA1 which points for code and data to the database MYDATA1, and has Global Mappings for a list of specific globals to the database MYDATA1TEMP.

(You can see this list If you go to the portal -> explorer -> Globals, and select in the first combo 'databases' and the second 'MYDATA1TEMP', you should see a limited amount of globals that will probably hold temporary data which is stored seprately from you other live data.)


Ideally, the backup should also backup the file cache.cpf to get a list of the configuration of namespaces, databases, and mappings.

Danny Wijnschenk · Jan 10, 2024 go to post

I had a similar problem where api calls could take up too much time to immediately respond.
So i immediately return as a response just a queryid (incremental number), which the user can use in a separate call to get the status, and in a separate call to get the results when the status is 'finished'.
Each call to the query api is stored in a table with the incremental queryid, the request and status='queued').
I have a job that will look at the next 'queued' request in the table that needs to be processed, set the status to 'in process', process the query, change the status in the table to 'finished' (and also store the results in the table).
So each query is processed one by one, and 'users' have to wait and use the status call to check when their query is processed. I also have a purge function that will delete processed queries after 14 days (so users can get the results within this period).
The api call that returns the next queryid will check if the background job is running to process the queue, if it is not running, it will job it. I also have put this method in the %ZSTART so it is started when Caché/Iris starts.
The background job in a loop process the queries, and will hang for a minute if there is nothing to do. (There are also ways in Caché/Iris to let the job 'sleep' and 'wake up'.)
 

Danny Wijnschenk · Nov 3, 2023 go to post

If the .DAT file was copied while Ensemble was running, it could be corrupt (there could be blocks that were written in memory but not yet to disk). The only reliable way to use a .DAT file as backup is when the file was copied while Ensemble was down, or when the file was dismounted. (the .lck file should not be present in the same directory as the .DAT file)
The good thing about a backupped .DAT file is that you can mount it as a new database, and copy stuff from it while the rest is still running as is.

Danny Wijnschenk · Oct 4, 2023 go to post

Hi Mark,
Glad to be of help, it was also fun for me, like an escape room where you need to get all clues to find your way out !
Of course, now you have the difficult task to accept all my answers as the best answer ;)

Danny Wijnschenk · Oct 3, 2023 go to post

Hi Mark,
I have tested this on my machine :
In the portal, add a role named 1 and give this role to your user besides the %All role.
Log in again in the portal and try the SQL, it should work now.
(In terminal, when you write $ROLES, it should say %All,1

Danny Wijnschenk · Oct 3, 2023 go to post

Hi Mark,
It is stated in the doc that %All is not enough : you have to have the exact role or be the exact username that matches row level security (in your case : the property FACILITY in each row).
Alternatively, you can disable it by setting the securitypolicy param to 0 (but then you need to recompile the classes that depend on it and rebuild the indices)
https://docs.intersystems.com/iris20232/csp/docbook/DocBook.UI.Page.cls…

Danny Wijnschenk · Oct 1, 2023 go to post

Hi Mark, If you can do inserts but not selects, the class might have row security enabeled.
Is there a parameter ROWLEVELSECURITY = 1, and a method %SecurityPolicy present ? In that method, you can exclude rows based on e.g. $username and $roles. Even if your user has the %All role, you could be excluded to see a row in this security.
If you see that, you can or create the correct user/role, or set the parameter to 0 (and rebuild all indexes).
Can you send the class definition of one of the tables, so I can try the class on my server ?

Danny Wijnschenk · Sep 30, 2023 go to post

Or in Terminal :
Do ##class(%ResultSet).RunQuery("DocM.DocumentImage","Extent")
(This should do the default query Select ID From table)

Danny Wijnschenk · Sep 28, 2023 go to post

Can you do the following (assuming the namespace USER is empty):
- copy the class definition of one class to the USER namespace (take a class that does not refer to other of your classes)
- do a SQL Insert into that table in USER
- do an SQL Select of that table in USER
- look if the global ^...D exists in USER.
- now copy the ^...D global from your orignal namespace to USER (using Merge command, or export/import in mgmnt portal) 
- Rebuild the indexes in USER of the class
- do the SQL Select again in USER

Danny Wijnschenk · Sep 28, 2023 go to post

In the DocM.DocumentImageD global, the first subscript is the id of each instance. Can you open such an id in terminal and look at the data 'the object way' by doing Set obj = ##CLASS(DocM.DocumentImage).%OpenId( id) and write he properties (like write obj.propxyz)

Danny Wijnschenk · Sep 28, 2023 go to post

Hi Mark,

What can you see in the management portal (Explorer -> SQL) when you click on a table in Catalog Details -> Maps/Indices : should list your globals that are being used.
What can you see when you click on Open Table ?
How about the user that you use : does it have %All rights? 

Have you tried opening an instance with Set obj = ##CLASS(DocM.DocumentImage).%OpenId( <some id> ) ?

Danny Wijnschenk · Sep 26, 2023 go to post

Hi Mark,
After the upgrade from Caché to Iris, it is best to recompile and upgrade the classes, that should correct any new syntax.
Can you try the rebuild of indexes after following commands :
 

Do $system.OBJ.CompileAll()
and
Do $system.OBJ.Upgrade()
Danny Wijnschenk · Sep 21, 2023 go to post

The exact index global for e.g. your class DocM.DocumentImage will by default be ^DocM.DocumentImageI (unless the class definition storage was changed).


You can rebuild the indices from the data by using the portal, click on the sql tabel and click on Actions->Rebuild indices.
Or go to terminal and Do ##class(DocM.DocumentImage).%BuildIndices()
(When doing an SQL query in the portal, you can view the query plan to see wheter an index was used.)

Danny Wijnschenk · Sep 21, 2023 go to post

Hi Mark,
In Iris, you can only get the label for a IRIS.DAT file, so you have to rename the CACHE.DAT to IRIS.DAT first

Danny Wijnschenk · Sep 20, 2023 go to post

Hi Mark,

Can you also check that you received the correct CACHE.DAT files by looking at the label inside the files (they might be copied from the wrong directories).
Do you still have the original .DAT files ? After renaming them from CACHE.DAT to IRIS.DAT, before you mount them in Iris, you can check the label stored inside the .DAT file.
when in terminal (%SYS) :
%SYS> Write $$ROOT^LABEL("c:\directory-unmounted-irisdat-file\")
It should display the original path of the CACHE.DAT from the Unix directory.

Danny Wijnschenk · Sep 20, 2023 go to post

Hi Mark,
Can you look in the definition of one of the classes/sql tables where you don't see any data : In Studio, when looking at the storage (bottom), which global is it using (usually name of the class + D) ? Where is this global mapped, and can you see this global in the database in management portal (System Explorer -> Globals).

Danny Wijnschenk · Sep 18, 2023 go to post

Can you check if the globals that are referred to by the table definitions are in any database ?
Can you look in the cpf file if they are mapped to another cache.dat.
 

Danny Wijnschenk · Sep 4, 2023 go to post

Hi Pedro,
Probably it has something to do with access rights : do you login with csp, else CSP is using the UnknownUser.
Can you check the result of the %Execute() call (listaPropriedades.%SQLCODE and listaPropriedades.%Message will have error values if the SQL could not run properly)

Danny Wijnschenk · Jul 26, 2023 go to post

The difference between embedded SQL (&sql() )and Dynamic (%ResultSet or %SQL.Statement) is that embedded is static and compiled in the code. You can only use parameters (preceded by colon) in the Where and Into Clause, but not change the SQL itself. You could write a bunch of If statements to call different &sql( ... ) code, depending the conditions, but if these combinations are to numerous you better use dynamic SQL.

Danny Wijnschenk · Jul 25, 2023 go to post

Hi Fabio,

I use the Iris Core license for applications that use REST heavily : you pay per core instead of per concurrent user.
It might be a better deal depending on:
- concurrent users
- CSP & REST usage
- CPU usage (how many cores does your server need to serve all users)

Danny Wijnschenk · Jun 25, 2023 go to post

Can you show us what you have coded in the catch block ? There should be no problem in handling your own error.

Danny Wijnschenk · Jun 13, 2023 go to post

Hi Dinesh,
I am working on a tool that is doing the following :
- create Swagger input file to enable manuel testing of api's (by adding enough comments in the resthandler/methods to generate this automatically)
- create UI to enter scenarios to automate unit/integration tests on api's:
-- call api's with parameters and compare response with expected status/response
-- use response of previous api's in a scenario to populate parameters for next api in scenario (e.g. post returns an id, next put will use the id to change, next delete will delete the id)
-- ability to run a scenario (set of api's) in a transaction, and to rollback in the end (by replacing actual REST call by in-process call)

Danny Wijnschenk · Jan 11, 2023 go to post

You can use 'client->name as clientname' and .%Get("clientname") or use .%GetData(columnnumber)