Using Cube Versions
This article describes how to use the cube version feature, which enables you to modify a cube definition, build it, and provide it to users, with only a short disruption of running queries.
This feature requires twice the amount of disk space, per cube. Also, this feature requires editing the cube class in Studio.
The cube version feature is not supported for a cube that defines a formally shared dimension. It is also not supported for a cube that defines a one-way relationship; it can be used with cubes that define two-way relationships.
Also see Accessing the Samples Shown in This Book.
Introduction to the Cube Version Feature
The cube version feature enables you to modify a cube definition, build it, and provide it to users, with only a short disruption of running queries. The feature works as follows:
A given cube definition can have versions.
The system generates a version-specific fact table and dimension tables for each cube version.
At any given time, only one cube version is active. The user interfaces and all generated queries use this version.
To make the newest cube version available, it must be activated. At this point, the system momentarily blocks any queries from being run and then switches to the newest version.
The following figure shows the overall process:
The cube logical name is redirected automatically to the active cube. The Analyzer and other user interfaces use only the cube logical name and thus see only the active cube. Similarly, if you use methods in %DeepSee.Utils and you specify the cube logical name without a version number, the system runs the method against the active cube.
When you update the cube version number (in Studio) and recompile, that creates a pending cube, which you can then build. When you are ready, you use a utility method to activate the cube, which causes the pending cube to become active and causes the previously active cube to become deprecated.
By default, the activation process automatically deletes the deprecated cube. The cube version feature is not intended to support switching back and forth between versions.
The best practice is to use source control. The cube version feature is not a replacement for source control, but can be helpful in conjunction with it.
Keeping the Cube Current
If a cube uses the cube version feature, you cannot build the active version of the cube. That is, the method $SYSTEM.DeepSee.BuildCube() does not affect the active version; instead an error is returned. The Build option in the Architect behaves the same way. These actions are blocked because they would disrupt running queries for a long time, and the goal of this feature is to prevent that disruption.
You can synchronize the cube.
Model Changes Can Break Queries
The cube version feature does not check to ensure that queries that function correctly on the active cube will function correctly on the pending cube. For example, if the pending cube no longer includes a model element that is defined in the active cube, any queries that use that element will not work when you activate the pending cube. It is the customer’s responsibility to identify model changes that could cause disruption and to handle such changes appropriately.
Modifying a Cube to Support Versions
To modify a cube so that it supports the cube version feature (and to create and activate the initial version):
Read this note if you are making a transition to cube versions and you have existing cubes that do not use this feature and you do not want any queries to be disrupted.
When you make the transition to cube versions, the process is different for the first cube version. Specifically, the first cube version should be runtime-compatible with the cube currently in use (the unversioned cube definition). This means that the first cube version should not remove or redefine any measures or levels, compared to the non-versioned cube definition. It can add elements; that has no effect on existing queries.
Add the following parameter to the cube class:
To make this change and the next, it is necessary to use Studio.
Add the following attribute to the <cube> element and then save the class:
Where versionnum is an integer.
Compile the class. Within the package generated by the system for this cube, there is now a new subpackage (named Versionversionnum). For example:
In this example, the new package is HoleFoods.Cube.Version1.
The classes HoleFoods.Cube.Fact, HoleFoods.Cube.Listing, HoleFoods.Cube.Star475620761, and so on existed previously; these were generated for the cube before USECUBEVERSIONS was added. The cube version utilities do not touch these class definitions.
Optionally make changes to the cube definition. Read the important note at the start of this section to decide which changes to make. Save your changes.
Build the cube. This step does not affect any running queries (nor do the preceding steps, provided that you follow the guidelines in the important note at the start of this section).
If you build the cube in the Terminal, the system displays slightly different output, to indicate that it is building a specific cube version. For example:
Building cube [HOLEFOODS:1]
In the Terminal, execute the %ActivatePendingCubeVersion() method of the class %DeepSee.CubeVersion.Utils. This method takes one argument, the name of the cube to build (without any version number). For example:
This method displays output like the following:
Pending version for holefoods: 1 Pending version synchronized: HOLEFOODS:1 Queries locked for cube: holefoods Killing active tasks for cube: holefoods Cube version activated: HOLEFOODS:1 Removing non-versioned cube data
One step of this method does briefly prevent queries from being executed against the cube; however, it is likely that users would not experience any actual delay.
Now all users see the new version of the cube.
If you are using the Cube Manager to update this cube, make sure that the update plan for the cube is either Synch Only or Manual. See Keeping the Cube Current.
Cube Versions and Relationships
You can use the cube version feature with cubes that are part of relationships. The rules are as follows:
All relationships must be two-way, rather than one-way.
Each of the related cubes must also specify a cube version.
When you update the version, build the new version, and activate the new version for any of the cubes, you must do the same for all the related cubes.
Activate the related cubes in the same order in which you build them. See Determining the Build Order for Related Cubes in Advanced Modeling for InterSystems Business Intelligence.
Details for %ActivatePendingCubeVersion()
The %ActivatePendingCubeVersion() method has the following signature:
ClassMethod %ActivatePendingCubeVersion(pCubeGenericName As %String, pRemoveDeprecated As %Boolean = 1, pVerbose As %Boolean = 1) As %Status
pCubeGenericName is the name of the cube, without version number. This argument is not case-sensitive.
pRemoveDeprecated specifies whether the method should also remove the cube version that is now being deprecated. If this argument is 1, the method removes the fact table and its data, dimension tables and their data, any cached data, and any internally used metadata for the cube version that is now being deprecated.
When you use this method for the first time, in the transition from a non-versioned cube, it removes the data stored in the fact table and so on for the non-versioned cube. It does not remove the non-versioned generated classes, which the system needs.
pVerbose specifies whether to display messages indicating the stage of processing of this method.
Updating a Cube Version
If you have not yet activated the first cube version, see the previous section. When you compile the first cube version, any changes to the cube would affect running queries, even before you activate the cube. Therefore it is necessary to compile, build, and activate one version of the cube that is runtime-compatible with the non-versioned cube; see the previous section for what this means.
If you have already modified a cube and created an initial version, use the following process to update the cube:
First modify the cube class so that it uses a new version number, in the <cube>element. This precaution prevents any cube changes from being visible too early. (Recall that some cube changes, such as to display names, take effect as soon as you compile a cube. See When to Recompile and Rebuild in Defining Models for InterSystems Business Intelligence.)
Save the cube class.
Make changes to the cube as wanted and save them.
Note that for a live system, you should test these changes on a different system first.
Compile the cube.
Within the package generated by the system for this cube, there is now another new subpackage with the new version number. For example:
Build the cube.
In the Terminal, execute the %ActivatePendingCubeVersion() method of the class %DeepSee.CubeVersion.Utils. In this case, this method displays output like the following:
Pending version for holefoods: 2 Pending version synchronized: HOLEFOODS:2 Queries locked for cube: holefoods Killing active tasks for cube: holefoods Cube version activated: HOLEFOODS:2 Deprecating previously active version: HOLEFOODS:1 Removing previously active version: HOLEFOODS:1
Within the package generated by the system for this cube, there is now only the subpackage with the new version number. For example:
Now all users see the new cube.
You can define subject areas based on a cube that uses the versioning feature. As with any change in a base cube, when you change a cube version, you must also recompile the subject area so it will function properly.
Specifying the Cube to Work With
When you use cube versions, you have the following options for specifying which cube to work with:
When creating a manual query in the Analyzer or in the MDX Query Tool, you can use either of the following forms of cube name:
The logical cube name. In this case, the query uses the active version of the cube.
The form cubename:versionnum where cubename is the logical cube name, and versionnum is the version number. In this case, the query uses the specified version.
In the Analyzer, Cube Manager, and other user interfaces, you can work only with the active version, with the exceptions noted in the previous bullet.
The user interfaces display the cube caption, which contains no information about the version.
Also, when you save changes, the saved data contains only the logical cube name (that is, without the version number), unless you typed a version number into a manual query. By default, definitions of pivot tables and listing groups do not contain version numbers.
When you use methods in %DeepSee.Utils that accept a cube name as an argument, you can use either the logical cube name or the form cubename:versionnum.
In the MDX shell, you can use either the logical cube name or the form cubename:versionnum. If tracing is enabled in the shell, the shell displays the cube version number.
The class %DeepSee.CubeVersion.Utils provides additional methods that you can use for debugging purposes. These include:
For details, see the class reference for %DeepSee.CubeVersion.Utils.
Also, the %BuildCube() of %DeepSee.Utils can return, by reference, the cube name with the active version number. For example:
SAMPLES>set cubename="patients" SAMPLES>set status=##class(%DeepSee.Utils).%BuildCube(.cubename) Building cube [PATIENTS:1] Existing cube deleted. Fact table built: 1,000 fact(s) (2 core(s) used) Fact indices built: 1,000 fact(s) (2 core(s) used) Complete Elapsed time: 0.461454s Source expression time: 0.298187s SAMPLES>w cubename PATIENTS:1
The method $SYSTEM.DeepSee.BuildCube() does not provide this option.
Disabling the Cube Version Feature
To disable versions for a given cube:
Modify the cube class and specify USECUBEVERSIONS as 0.
Save and compile the class.
Build the cube.
Optionally delete the cube versions that are no longer needed. Execute the following command in the Terminal:
Where cubename is the logical cube name, and versionnum is the version number.
This method returns an error if you attempt to remove the active version.
From this point on, the cube behaves the same as a non-versioned cube.