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:
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! |
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:
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?
It's available in 2017.2 in %SYS namespace.
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.
Here's it in class doc. You can only see it in class explorer for %SYS namespace.
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.
Right.
@Alexey Maslov does exactly that at the beginning of his code sample:
Missed that bit. I was only looking at the part I wanted. Such a typical developer thing to do