Lucas Fernandes · Jan 23, 2023 go to post

In Caché, as an alternative to Portal, you can use Terminal and run:

SAMPLES>do $SYSTEM.SQL.Shell()

SQL Command Line Shell
----------------------------------------------------

Or the %SQL.Statement

Or try an external tool like dbeaver (https://dbeaver.io/)

Lucas Fernandes · Mar 22, 2023 go to post

The same example but in a different form:

    try {

        set result=##class(%ResultSet).%New("%DynamicQuery:SQL")
        $$$ThrowOnError(result.Prepare("SELECT ... "))
        
    } catch error {
        do error.Log()
    }

The error details will be in the Application Error Log

Lucas Fernandes · Mar 29, 2023 go to post

You can try to change using Config.SQL class.

Example:
 

%SYS>w$SYSTEM.SQL.CurrentSettings()
ODBC VARCHAR Max Length:                     4096 (Default)

%SYS>do##class(Config.SQL).Get(.p)
%SYS>zw p("ODBCVarcharMaxlen")
p("ODBCVarcharMaxlen")=4096%SYS>set p("ODBCVarcharMaxlen") = 5120%SYS>do##class(Config.SQL).Modify(.p)

%SYS>w$SYSTEM.SQL.CurrentSettings()
ODBC VARCHAR Max Length:                     5120
Lucas Fernandes · May 29, 2023 go to post

This process is related to the Caché System Monitor. Monitors various resources, including the Journal.

"Caché System Monitor is a flexible, user-extensible utility used to monitor a Caché instance and generate notifications when the values of one or more of a wide range of metrics indicate a potential problem."

You can Stop them or customize the Sampling Interval for your environment.

See more in the documentation Caché System Monitor  and Caché Monitor

Lucas Fernandes · Aug 17, 2023 go to post

You can create User Events using the Security.Events class, with the Create method.

Example:

%SYS>w ##class(Security.Events).Create("Source","Type","Name","Description", 1)
Lucas Fernandes · Sep 15, 2023 go to post

Hi Shen Jun,

If you installed Caché on Windows before installing the Windows SNMP service. You need to register the DLL in Caché. Open the Terminal and type:

%SYS> set status=$$Register^SNMP()

Then restart the Windows SNMP service and start the Caché SNMP service.

Documentation: SNMP Troubleshooting

Have you already done this step?

Lucas Fernandes · May 3, 2024 go to post

Maybe it can help,

In the SYS.Database Class you can find the IsSystemDB(Directory) method that returns whether it is a system database.
It works on Caché and IRIS.

Documentation IsSystemDB - IRIS

Documentation IsSystemDB - Caché

Examples:

%SYS>set databaseDir = ##class(Config.Databases).Open("IRISLIB").Directory

%SYS>write ##class(SYS.Database).IsSystemDB(databaseDir)
1
%SYS>set databaseDir = ##class(Config.Databases).Open("CACHELIB").Directory

%SYS>write ##class(SYS.Database).IsSystemDB(databaseDir)
1

Hi Philip,

Another way is to use the ##class(Backup.General).IsWDSuspendedExt() routine.
According to the documentation:


"When called in an external script, exit status is set to 5 if WD is suspended or 3 otherwise."

Example:

irisowner:~$ iris terminal IRIS -U%SYS "##class(Backup.General).ExternalFreeze()"
irisowner:~$ iris terminal IRIS -U%SYS "##class(Backup.General).IsWDSuspendedExt()"
irisowner:~$ echo $?
5
irisowner:~$ iris terminal IRIS -U%SYS "##class(Backup.General).ExternalThaw()"
irisowner:~$ iris terminal IRIS -U%SYS "##class(Backup.General).IsWDSuspendedExt()"
irisowner:~$ echo $?
3

If the access is via SQL (INSERT, UPDATE), it is possible.
You can create a role with RW access to the database resource and grant INSERT privileges without the SELECT privilege.

If the access is via Global (SET), it is not so simple. Because you need to grant RW permission to the Database Resource and, consequently, the user will be able to read the data from the global resource.

For example, you create the logs_w role and grant it to the user 

%SYS>do ##class(Security.Roles).Create("logs_w", "", "%DB_LOGS:RW")
%SYS>do ##class(%SQL.Statement).%ExecDirect(,"GRANT logs_w TO appuser")

%SYS>set $NAMESPACE="LOGS"
LOGS>do ##class(%SQL.Statement).%ExecDirect(,"GRANT INSERT ON app.Log TO logs_w")

If the user tries to execute a SELECT they will receive an error

LOGS>do $SYSTEM.Security.Login("appuser")
LOGS>do $SYSTEM.SQL.Shell()
[SQL]LOGS>>SELECT * FROM app.Log

ERROR #5540: SQLCODE: -99 Message: User appuser is not privileged for the operation

If the user tries to execute an INSERT, it will succeed.

[SQL]LOGS>>INSERT INTO app.Log VALUES ('Test 1')
1.    INSERT INTO app.Log VALUES ('Test 1')

1 Row Affected
---------------------------------------------------------------------------

But this permission is not valid for globals, the user will be able to read

LOGS>zw ^app.LogD
^app.LogD=1
^app.LogD(1)=$lb("","Test 1")

In this case you can follow other strategies, such as Applications and Privilege Escalation. Here you isolate the database and the user does not have default access when logging in. Access is granted temporarily when executing a method/routine. A simple example:

In a database to which the user has default access, create a method that receives temporary privileges to write to the protected database

Class service.Log
{

ClassMethod write(msg As %String) As %Status
{
   do $SYSTEM.Security.AddRoles("grant_logs_w")
   new $NAMESPACE
   set $NAMESPACE="LOGS"
   do ##class(%SQL.Statement).%ExecDirect(,"INSERT INTO app.Log VALUES (?)", msg)
   return 1
}

}

Create a Privileged Routine Applications for this method

set p("Name") = "grant_logs_w"
set p("CookiePath") = "grant_logs_w/"
set p("Description") = "Applications and Privilege Escalation"
set p("Type") = 4
set p("Resource") = "%Development"
set p("AutheEnabled") = 64        
set p("Enabled") = 1
set p("MatchRoles") = ":logs_w"
set p("Routines") = "service.Log:APP:1"
do ##class(Security.Applications).Create("grant_logs_w", .p)

The user does not have access to the LOGS database, but can execute the write method with temporary privileges.

APP>w $ROLES
%Developer,%DB_APP
APP>do ##class(service.Log).write("Test 2")