Detecting Orphaned Objects in Production
One thing that has always annoyed me about MicroStrategy Object Manager is it’s insistence to migrate schema objects with even the slightest excuse. In the same vein as Quantum Mechanics, “when things get small they get weird”, the same is true in the MicroStrategy metadata. The Metadata Dependency table keeps all of the relationships between objects, for example, a Report is a parent of the Metric that is added to it. But this rule breaks down with Attributes and Tables. An Attribute is a parent of it’s Table, but a Table is also a parent of it’s Attributes. This strangeness creates what I call “Schema Spidering” in Object Manager, where effectively everything is related to everything some way or the other. This means if you create a new attribute, and then migrate a completely unrelated report, Object Manager will find a way to get that new attribute over and you (usually) can’t prevent it. There are some settings to prevent this “spidering”, but for various reasons I don’t feel comfortable disabling them, so I deal with the freeloaders to Production.
The problem this causes is not only that you could end up with Developmental and untested schema changes in Production, but inevitably you’ll end up with objects in Production that no longer exist in Development (Orphans). This could lead to inconsistant testing results or worse. Today, I’ll share a quick script to detect these orphans so that you can monitor them and take action.
This SQL script is written based on a MS-SQL Metadata, and should be easy to adjust for different platforms. In essence, it will compare two projects (Production vs Development) and list objects that are in Production and not Development. You could wrap this into a Freeform SQL Report and subscribe it to yourself to receive notifications of when this occurs, and then take actions on those objects.
drop table #folders
select o.project_id, p.object_name as project_name, o.project_id as parent, p.object_name as parent_name, o.object_id as folder, o.object_name as folder_name
From dssmdobjinfo o
join dssmdobjinfo p
on o.project_id = p.object_id
join dssmdobjinfo r
on o.parent_id = r.object_id and o.project_id = r.project_id
where r.object_name in('Public Objects', 'Schema Objects') and o.PROJECT_ID = 'PRODUCTION PROJECT GUID'
while @@rowcount > 0
insert into #Folders
select o.project_id, f.project_name as project_name, o.parent_id as parent, p.object_name as parent_name, o.object_id as folder, o.object_name as folder_name
from dssmdobjinfo o
join #folders f
on o.project_id = f.project_id and o.parent_id = f.folder
join dssmdobjinfo p
on o.parent_id = p.object_id and o.project_id = p.project_id
where o.object_id not in(select distinct folder from #folders)
and o.object_type = 8 and o.subtype = 2048 and o.hidden = 0
select p.OBJECT_TYPE, p.OBJECT_NAME, p.DESCRIPTION, p.CREATE_TIME, f.folder_name
from DSSMDOBJINFO p
join #folders f
on p.PARENT_ID = f.folder
left join (select * FRom DSSMDOBJINFO where PROJECT_ID = 'DEVELOPMENT PROJECT GUID') d
on p.OBJECT_ID = d.OBJECT_ID
where p.PROJECT_ID = 'PRODUCTION PROJECT GUID'
and d.OBJECT_ID is null
The first 2 sections of the script are used to build a list of folders under Public Objects and Schema Objects. The reason you’ll want to do this is because you’ll surely get lots of “Orphan” hits for user’s objects in My Reports, so this is the best way I’ve found to isolate Public/Schema Objects only.
Once we have that, we can join it to the list of objects in Production, and then compare that to the list of objects in Development. The resulting list is our culprits!
Unfortunately, the Metadata does not provide a lookup table for Object Types, and you may want to adjust some of the things you’re considering Orphaned (for example, exclude Shortcut objects). It may also make the report easier to take action on if it told you an orphan was a “Report” instead of “3”. To implement this, simply create your own lookup table for Object Type in your metadata, and add it to the 3rd part of the query. You can obtain a list of Object Types from this Tech Note.
UPDATE: Object IDs are handled differently in 9.2+, so be sure to check out Changes to Object IDs in 9.2