But this also means that you can't ship the whole vendor copy of the global as you will overwrite the onsite ID counter node.

You can! When you load globals specify /mergeglobal flag to merge the global with existing data instead of overwriting it:

set sc = $system.OBJ.Load("global.xml", "/mergeglobal=1")

seed the ID counter at the site to a really high number

Bitmap indices would really slow down from that.

This applies to properties of a class correct? Not just methods?

Correct.

You have several solutions:

  1. Application level control. You have one table Term { Name, Type} and on the application level you decide for edits to go or not based on type. It is the fastest solution, but you need to write a application code and remember to check for type.
  2. Class-level control as described by you.
  3. Row-level security. Control access row by row.

The easiest way is to use JSON_OBJECT for everything. Fastest would be just writing to device from resultset. Combine these approaches to get the performance you need (add this code to Parent class and call Test method):


Query Display() As %SQLQuery
{
SELECT
    JSON_OBJECT(
        'ID':%ID,
        'Name': Name,
        'Description': Description,
        'Children':    Example.Parent_GetChildrenInfo(%ID)
    )
FROM Example.Parent
}

/// do ##class(Example.Parent).Test()
ClassMethod Test(count = 0)
{
    if count>0 {
        do ##class(Example.Child).%KillExtent()
        do ..%KillExtent()
        
        
        do ##class(Example.Child).Populate(count,,,,$$$NO)
        do ..Populate(count,,,,$$$NO)
    }
    
    do ..DisplayFunc().%Display()
}

ClassMethod GetChildrenInfo(id) As %String [ SqlProc ]
{
    #define CRLF                             $c(13,10)
    #define ZENJSISNUM(%val)                ($IsValidNum(%val)&&(%val=+(%val)))
    #define ZENJSNUM(%num)                    $fnumber(%num,"LON")
    #; JSON utility macros that use the JSON translation table instead of the JS translation table
    #define ZENJSTABLE(%format)                ("JS"_$S(%format["u":"ML",1:""))
    #define ZENJSONTABLE(%format)            ("JSON"_$S((%format["u"):"ML",1:""))
    #define ZENJSONESCAPE(%str,%format)        $S(%format["s":$ZCVT(%str,"O",$$$ZENJSONTABLE(%format)),1:$Replace($ZCVT(%str,"O",$$$ZENJSTABLE(%format)),"\'","'"))
    #define ZENJSONSTR(%str,%format)        (""""_$$$ZENJSONESCAPE(%str,%format)_"""")
    #define ZENJSONPROP(%prop,%format)        $$$ZENJSONSTR(%prop,%format)
    #define ZENJSONVALUE(%val,%format)        $S($$$ZENJSISNUM(%val):$$$ZENJSNUM(%val),$C(0)=(%val)||$ListValid(%val):"""""",1:$$$ZENJSONSTR(%val,%format))
    #define ZENJSONPAIR(%pr,%val,%format)    $$$ZENJSONPROP(%pr,%format)_":"_$$$ZENJSONVALUE(%val,%format)
    
    set out = "["   
    
    
    set ids = ..ChildrenGetStored(id)
    set ptr=0
    set separator=0
    while $listnext(ids,ptr,value) {
        set value = $lg(value)
        set:separator out = out _ ","

        set out = out _  "{"
        set out = out _  $$$ZENJSONPAIR("Name",##class(Example.Child).NameGetStored(value),"") _","
        set out = out _  $$$ZENJSONPAIR("Description",##class(Example.Child).DescriptionGetStored(value),"")
        set out = out _  "}"
        set separator = 1
    }
    
    set out = out _  "]"
    
    quit out
}

I once separated one Ensemble database (with code and data) into two databases (one db for code, one db for data) on a running system.

It was not difficult actually:

  1. Exported code from one database
  2. Created new database.
  3. Imported code into new database.
  4. In a namespace switched code database from old database to a newly created one.
  5. Deleted classes from old database.

But in my situation the code itself didn't change.

Well, what do you want to do with that list? Depending on your use case, the solution may differ.

For example to get a list of dashboards execute this query:

SELECT *
FROM %DeepSee_Dashboard.Definition

And to get a list of Pivots execute this one:

SELECT *
FROM %DeepSee_Dashboard.Pivot

And in MDX2JSON project I need to get a list of dashboards visible to the current user.  I use custom result set for that (because user may have access to dashes but not to SQL).