Operational Differences between MultiValue and Caché
MV Accounts and Caché Namespaces
Both MV and Caché have the concept of a logical space to hold groups of related programs and data. In MV, this space is called an ACCOUNT; Caché calls it a NAMESPACE
. Because of this similarity, it is natural to consider mapping MV accounts to Caché namespaces since this will also provide the easiest access to all the other facilities that Caché provides for MV applications.
Similarity is not identity, however. The rules for forming MV account names differ from those for Caché namespaces. The following describes the differences between them and how those difference are resolved.
An MV account name could contain any character from the extended ASCII character set.
Caché namespace names are at least one character long, starting with an alphabetic character or a percent sign, and followed by an arbitrary number of alphanumerics, dashes or underscores.
In the simplest case, a Caché namespace maps to a Caché database of the same name. Caché database names are between 1 and 30 characters long, can start with an alphabetic character or an underscore. The remaining characters can be alphanumeric, dash, or underscore.
Converting the Account Name
In transforming the account name for Caché, it is desirable to end up with a result that doesn't alter simple names, that transforms non-conforming account names in an obvious way, and that results in a string acceptable for both the namespace and the database name. To that end, the following algorithm is used to transform an MV account name into the required Caché namespace and database names. AName, NSName, and DBName stand for the MV account name, Caché namespace name and Caché database name, respectively.
Start with an empty NSName.
Scan AName from left-to-right finding the first alphanumeric character. Make this the first character of NSName.
Continuing from the character just found, append all following characters of AName to NSName in the order scanned as long as each is an alphanumeric, dash or underscore.
If the resulting NSName is SYSPROG, set NSName to %SYS (the Caché administrator namespace).
If NSName is empty (no suitable characters were found), set NSName to the string ACCT_NIL.
If NSName is longer than 27 characters, set NSName to the string "ACCT_TRUNC_nnn_1", where nnn is the length of the original account name.
Convert NSName to uppercase.
Set DBName equal to NSName.
Resolving Duplicate Namespace Names
When creating a new MV account within Caché, it is possible that the preceding algorithm will result in a namespace name that already exists. In this instance, additional processing is done to make the namespace name unique so that the creation of the new account succeeds.
If the name does not ends in an underscore followed by a string of digits, "_1" is appended to the name.
Repeatedly do the following until a unique name results:
Extract the string of digits following the last underscore.
Increment the integer formed by this string of digits by one.
Replace the extracted string of digits by the new value.
When creating a new MV account names, for example when importing MV applications, Caché keeps track of the original account name and its resulting namespace name. This map is used to ensure that references in the MV application to other MV account are properly resolved.
When an account name is deleted, it is removed from this map.
Dictionary Items Single Versus MultiValued
The basic rule for dictionary entries in Caché is this: unless you are certain that the field will always be single-valued, mark it as multivalued or just leave the M/S indicator blank. This is because setting an entry as single valued allows the query processor to optimize the generated code, and generally this optimized code will not work correctly on multivalues.
If you have an I-type dictionary attribute, regardless of whether it is marked single or multivalued, the I-type expression processes the entire data record at once. In the I-type expression, you can choose to use single-valued functions like OCONV, or multivalued functions like OCONVS, so you can control whether multivalues are processed as one string (using OCONV), or as multivalues (using OCONVS).
This processing is independent of whether the attribute is marked as single or multivalued.
After processing the I-type expression, the result is passed through the option conversion in attribute 3 of the dictionary item 1 value at a time, again regardless off single or multivalued identification.
The usage of the attribute varies with whether it is marked as single or multivalued. If the data is multivalued, but the attribute is marked as single-valued, then a comparison against a single value will likely fail. For example:
SELECT FILE WITH ATRB = "ABC"
where the actual data in ATRB is something like ABC]DEF
will pass if ATRB is marked multivalued, but will fail if it is marked single-valued, because on a multivalued compare, ABC
is compared separately against ABC
, but on a single valued compare, ABC
is being compared against the entire string ABC]DEF
and is not equal.
If an attribute is marked as single-valued, then the results of an exploded select or WHEN clause will be different than if it were marked multivalued.
This is true on Caché and all platforms that support I- and D-type dictionary attributes.
For A-types, the rules are slightly different. No other platform besides Caché allows an A-type to be marked single-valued. On UniVerse ODBC, A-types can be identified as single-valued, but this has no effect on MultiValue query.
On any platform, when an A-type is multivalued, the correlative on attribute 8 of the dictionary is called repeatedly, once for each value in the data. This is in contrast to an I-type where the I-type expression is only run once. However, as with the I-type, the conversion (attribute 7 in an A-type) is applied to each value.
On Caché, when an A-type is single-valued, the results depend on the type of correlative. For a simple correlative like MCT, the entire data attribute, including all multivalues, is passed through the correlative as one string. If the attribute data is something like ABC]DEF, then the result of the MCT correlative will be Abc]def, as opposed to Abc]Def which would be produced by a multivalued attribute. Then the conversion is applied one value at a time. So a single-valued A-type with a simple correlative will process like a single-valued I-type.
If the correlative is an A, F or C processing code, then the data will be passed through the correlative once, but each attribute reference in the correlative will only get the first value of the attribute it references. For example if the correlative is F1, and attribute 1 contains ABC]DEF
, the result of the correlative will be just ABC
. The second value never gets processed.
So, it is ill-advised to ever use an A, F or C processing code in a single-valued attribute if there's any chance the processed data might be multivalued. This applies not just to the data in the AMC (Attribute 2 of the dictionary item) but also if any of the other attributes the correlative references might be multivalued.