Question
· Sep 24

How to Merge Contents from Multiple Routine Databases into a Common Target Database

I am working on a tool that configures an instance to use a common default routine database across all custom Namespaces. For instances that already have distinct default routine databases for their Namespaces, this would involve a step of merging over all code from the current default routine databases to the new "super" routine database. This should be done in such a way that only merges contents in the default routine database (not mapped databases) and is able to detect/exclude contents that already exist in the target database.

Are there any supported tools/APIs for merging routine database contents to help accomplish this? I should clarify there is no guarantee as to what packages may or may not be present in the default routine databases and no guarantee as to what packages may be mapped from other databases. The goal is to allow a user to run this tool and be able to seamlessly access and run code previously stored in default routine databases from any of their custom Namespaces.

Discussion (11)5
Log in or sign up to continue

To merge the contents of multiple routine databases into a common target database, and ensure only routines in the default routine database (not mapped databases) are merged while excluding duplicates, several classes and APIs can assist in accomplishing this:

  1. Use %Routine Class:

    • %Routine class provides methods to manipulate routines programmatically, such as RoutineExists(), which can be used to check if a routine already exists in the target database before merging.
    • Other relevant methods include Compare(), RoutineList(), and Save() for exporting and saving routines.
    • This API supports creating, compiling, and modifying routines programmatically, making it suitable for tasks involving merging routine contents [1].
  2. Use %SYSTEM.OBJ Class:

    • This class includes methods such as Export(), ExportToStream(), and Load() to facilitate the export and import of routines between databases.
    • These methods are useful for exporting routines from the source databases and loading them into the target database while managing duplicate entries by pre-checking if the routine exists using the %Routine class [1].
  3. Routine Detection and Exclusion:

    • You can programmatically query routines in the current default routine database and cross-check against the routines already present in the target database before importing, using classes like %Routine and %RoutineIndex which provide routine information and indexing capabilities [1].
  4. Namespace Considerations:

    • Routine mappings can be configured through the Config.MapRoutines class or directly in the Management Portal. However, ensure that routine mappings in non-default databases are not mistakenly merged [1].

These tools allow for flexible and controlled merging of routine contents across databases, adhering to your requirements regarding default versus mapped databases and avoiding duplicates.

Relevant References:
- Tools and methods for working programmatically with routines [1].

Sources:

A common mapped database is essentially the end result. The question here is not asking about the end result, but rather how we get there for an already existing system. Say we have a customer with an instance that already has a good deal of custom code across multiple databases. How do we move all of this code spread across multiple default routine databases to a single location so then all Namespaces can use a mapping to access it in one place?

Tricky bit there is forming that list. DataMove seems to be per source Namespace rather than per source database.  Is there a good way to get a list of all relevant contents from a specific routine database? This would be all classes, mac routines, int routines, projects, and more, but only those that are defined in the default routine database with care to not move mapped items.

You are right. $system.OBJ.Export~whatever is oriented to the Namespace

BUT:
There still seems to be no limitation to map a specific database file
to more than 1 namespace. e.g. USER and MERGER (here Read Only)
Then $system.OBJ.Export~whatever takes what it finds in MERGER.
It's quite a dirty approach and only meant for READING the code, therefore, ReadOnly

In any case, it's safer just to copy the (most likely static) DB of interest
and use it in MERGER
 

Very clever! Yes, I think I could create a Namespace that points to just the routine database of interest, merge over contents to target (since everything from that MERGER Namespace is desired), use this intermediary for each database of interest, then clean up at the end. Per Eduard's point above regarding conflicts, is there any way to pre-empt conflict using such tooling? If 2 databases have a class of the same name defined, how can I prevent clobbering the contents merged from the first database when I merge the second? Even if it is a conservative approach of failing to move code if there is any overlap, I think that would be preferable to overwriting existing code.

From Class Docs:
• classmethod ExportAllClassesIndividual(dirname As %String = "", qspec As %String = "", ByRef errorlog As %String, Charset As %String = "", Package As %String = "*", SubDir As %Boolean = 0) as %Status

Export all the classes as individual XML files to a directory.

This method loops through all the classes, exporting each one as an individual XML file named after the classname to the directory dirname. If you specify a Package, then it exports only this package. If SubDir is true,, the method exports sub-packages as subdirectories.

Now the directory is your list of classes and equal sizes of files 
might most likely mean identical content. Or you do a text compare

I could do exports of contents from each database, accumulate these in a common directory only adding files if not already present, and then load everything in from this directory at the end. I was looking to avoid this approach if possible since I really just need database contents to move locally but if this needs to turn to OS file system exports, then that is a valid approach. I just need to be sure to export all of each item type that is present in the routine database (classes, routines, projects, etc) and import them using their respective APIs. Should a category of item that is stored in a routine database be added in the future I would need to account for this and explicitly add it to the list.