Where is my global stored?

It's well-known that namespace global mapping helps us to write code independent on database storage details (Caché instance name, directory path). But sometimes we can face problems accessing an unsubscripted global which has subscript level mapping (SLM) defined. Most of such cases are evident and associated with administrative tasks that should be done on database level, but some of them can confuse even an experienced developer. Just to start:

  • We can't export such a global using Caché Block format (a.k.a. GOF).
  • We can't kill such a global.

Maybe you can continue this list.

Each of these problems can be easily solved could we get a list of databases where the parts of a given global reside. Here is my quick solution:

map(pNsp, pGlb) Public ; list all maps of SLMapped globals, searching the given (unsubscripted) one
{
  new $namespace
  try {
    set $namespace="%SYS"
    set sc=1
    set:$extract(pGlb)="^" $extract(pGlb)=""
    ; query List(Namespace As %String, Names As %String = "*", CPFFile As %String = "", Flags As %Integer = 0)
    set rset=##class(%Library.ResultSet).%New("Config.MapGlobals:List") 
    ; Selects Name As %String, Global As %String, Subscript As %String, Database As %String, Collation As %Integer, LockDatabase As %String 
    set sc = rset.Execute(pNsp,pGlb_","_pGlb_"(*")
    while rset.Next() 
      if (rset.Data("Global")=pGlb) {
         write !,rset.Data("Name")," ",rset.Data("Global")," ",rset.Data("Subscript")," ",rset.Data("Database"),!
         set sc1=##Class(Config.Databases).Get(rset.Data("Database"),.prop)
         if sc1 {
             set dir=prop("Directory")
             set ref="^|""^"_prop("Server")_"^"_dir_"""|"_pGlb
             try {
                 write ref," ... ",$data(@ref),!
             catch {
                 write $zerror,!
                   set sc=$$$ADDSC(sc,$$$ERROR($$$CacheError,$zerror))
             }
         else {
             set sc=$$$ADDSC(sc,sc1)
         }
      }
    }
  catch {
      write $zerror,!
      set sc=$$$ADDSC(sc,$$$ERROR($$$CacheError,$zerror))
  }
  if $isobject($get(rset)) do rset.Close()
  quit sc
}

E.g., for global mapping defined as follows:

The global mappings for namespace QMSTEST8 are displayed below:
     
 Filter:  Page size:  Max rows:  Results: 2  Page: |‹‹‹1›››|of 1  
   Global Subscript Database     
 zQ QMSDEVELDBEditDelete
 zQ("0!"):(END)CACHETEMPEditDelete

my procedure gives a result:

USER>d map^db.82U("QMSTEST8","^zQ")

zQ zQ  QMSDEVELDB
^|"^DEVEL^D:\InterSystems\devel\mgr\qms\"|zQ ... 10

zQ("0!"):(END) zQ ("0!"):(END) CACHETEMP
^|"^^D:\InterSystems\test\mgr\cachetemp\"|zQ ... 10

HTH somebody. Happy coding!

Comments

The result set of Config.MapGlobals:List query can be restricted to the global of interest (pGlb) records if change the Names search criteria in Execute call to:

    set sc = rset.Execute(pNsp,pGlb_","_pGlb_"(*")

Snippet's code was amended.

I am using Ensemble 2017.2 and the Config.MapGlobals query is not available.

Do you know how I can list the mapped globals of a namespace on 2017.2?

Thanks. I will try from the %SYS namespace. I was trying to access it in another namespace. It also does not show in the class explorer. One of those "hidden" features.

Thanks. Appreciate it. If  I'm writing a method that uses this class in another namespace, I should be able to just zn to %SYS in the code in order to use the class.

Missed that bit. I was only looking at the part I wanted. Such a typical developer thing to do wink