Multi-Value and Range-Value Attributes

Attributes can have multiple values and can also specify a range of values. Multi-value attributes also support the existing concept of ranges. For more information, see MQL Command Reference: Add Attribute Command.

This page discusses:

Multi-Value Attributes

Traditionally, an attribute can specify only one value. If an app needed an attribute to have multiple values, stored as comma-separated values it would need to add logic to parse the comma-separated values and display them properly. However, the core system would not be aware of the workaround convention and it could lead to issues when searching or indexing the data. To deal with these issues, MQL provides the following support for multi-value attributes:

  • Multi-value attributes can be applied to any attribute type, including date, integer, real, Boolean, and string.
  • Multi-value attributes can define an order. An order number is used to display the attribute values in a specific order.
  • Dimension can be applied to the numeric fields.
  • Each value can have its own unit of measure when Unit Of Measure (UOM) is applicable.
  • Searching is performed against each value separately to determine a match.
  • A multi-value attribute can have more than one instance of the same value.

You define an attribute to be multi-value by specifying its type as multivalue at the time of creation. You can also provide an order number when setting a multi-value attribute so that its value is positioned correctly.

To define an attribute as multi-value, use this command:

add attribute NAME multivalue;

To define an attribute as single-value, use one of these commands:

add attribute NAME notmultivalue;
add attribute NAME !multivalue;
add attribute NAME;

By default, attributes are single-value. You cannot specify default values for multi-value attributes. Import and export can handle multi-value attribute definitions and instances.

The lxString table indexes support multi-value attributes as follows:

  • The index on lxType, lxVal, lxOid is only LxType, lxVal. In addition, the index order is lxType, lxVal on all databases.
  • The unique index on lxOid, lxType includes the non-key column lxVal on SQL Server.

Range-Value Attributes

While multi-value attributes allow you to enter distinct values, range-value attributes allow you to enter maximum and minimum values (for example, to model a range of 100% - 20%). This capability is enabled for numeric fields and dates (for example, to model a start and end date).

MQL provides the following support for range-value attributes:

  • Range-value attributes can be applied to numeric and date attributes.
  • Dimension can also be applied to the numeric fields.
  • The range can have only one UOM value.
  • Searching is performed against both values.
  • When setting values for a range-value attribute, you can specify either endpoint as inclusive (by default), exclusive (using the keywords minexclude and maxeclude), or open-ended (if no value is specified).

You define an attribute as having a range by specifying its type as rangevalue at the time of creation. Only numeric and date attribute types can be defined as range-value attributes. If you attempt to define a string or Boolean attribute type as rangevalue, an error will be thrown.

To define an attribute as specifying a range of values, use the command:

add attribute NAME rangevalue; 

To define an attribute as not specifying a range, use one of the commands:

add attribute NAME notrangevalue; 
add attribute NAME !rangevalue; 
add attribute NAME;

By default, attributes do not specify a range of values. You cannot specify default values for range-value attributes. Import and export can handle range-value attribute definitions and instances.

For more information, see MQL Command Reference: attribute Command.

Modifying Multi-Value Attributes

To modify an existing attribute to become multi-value, use this command:

modify attribute NAME multivalue;

Only existing singlevalue attributes can be modified to become multivalue. If the attribute is already a rangevalue, an error will be thrown. If there are instances of a singlevalue attribute in the database, the modification moves all instances from the existing attribute tables to the new multi-/range-value attribute tables in the database.

If an attribute is already multivalue and has multiple values (instances), changing it to singlevalue is not allowed and will cause an error to be thrown. For example, you can use either of the following commands to change a multivalue attribute to singlevalue:

modify attribute NAME notmultivalue; 
modify attribute NAME !multivalue;

The above is valid if the attribute is already either multivalue or rangevalue and instances exist.

If the attribute is not already multivalue, you can use the following command. This syntax is permitted for a singlevalue attribute with no instances.

modify attribute NAME rangevalue;

The above is OK if the existing rangevalue attribute does not have any instances in the database. If the attribute is already specified as multivalue, an error will be thrown. The following table shows a summary of what is permitted and what is not:

Modification Allowed?
From To
singlevalue (without any instances) rangevalue Yes
singlevalue (with instances) rangevalue No
singlevalue (without any instances) multivalue Yes
singlevalue (with instances) multivalue Yes
rangevalue (without any instances) singlevalue Yes
rangevalue (with instances) singlevalue No
rangevalue (without any instances) multivalue No
rangevalue (with instances) multivalue No
multivalue (without any instances) singlevalue Yes
multivalue (with instances) singlevalue Yes (as long as there is only one value for each instance)
multivalue (without any instances) rangevalue No
multivalue (with instances) rangevalue No

If the existing rangevalue attribute does not have any instances in the database, you can use one of the following commands. If the attribute is already specified as multivalue, an error will be thrown.

modify attribute NAME notrangevalue; 
modify attribute NAME !rangevalue;

This table defines if an attribute conversions is allowed:

Modification Allowed?
From To
singlevalue (without any instances) rangevalue Yes
singlevalue (with instances) rangevalue No
singlevalue (without any instances) multivalue Yes
singlevalue (with instances) multivalue Yes
rangevalue (without any instances) singlevalue Yes
rangevalue (with instances) singlevalue No
rangevalue (without any instances) multivalue No
rangevalue (with instances) multivalue No
multivalue (without any instances) singlevalue Yes
multivalue (with instances) singlevalue Yes (as long as there is only one value for each instance)
multivalue (without any instances) rangevalue No
multivalue (with instances) rangevalue No

Adding or Modifying Business Objects or Connections for Multi-Value and Range-Value Attributes

When a multi-value or range-value attribute has been added to a type or relationship, you can add business objects and connections with attribute values. You can provide a comma-separated list of values for a multi-value attribute using one of the following methods:

add bus T N R ATTR_NAME 1,2,3; 
mod bus T N R ATTR_NAME 3,4,5; 
mod bus T N R ATTR_NAME test1,test2,test3;

If the values themselves have spaces or commas, then they must be passed in single or double quotes using one of the following methods:

mod bus T N R ATTR_NAME 'foo bar1','foo bar2',foo bar3';
mod bus T N R ATTR_NAME "foo bar1","foo bar2","foo bar3";

Attempting to provide a comma-separated list of values for an attribute that is not multi-value will cause an error to be thrown.

For range-value attributes, the keywords minexclude and maxexclude indicate that the range endpoints do not include the minimum and maximum values, respectively. This is similar to interval notation in algebra.

Range-value attributes can have the following possible values:

Values Description
minval::maxval

For example:

 5::10

  • Both minval and maxval are included for any query operation. In the example, it considers the value of the range from 5 to 10 (i.e., including 5 and 10).
  • The selectables includeminval and includemaxval both return TRUE.
minval::maxval minexclude

For example:

5::10 minexclude

  • Only maxval is included for any query operation. In the example, it considers the value of the range from 6 to 10 (excluding 5).
  • The selectable includeminval returns FALSE.
minval::maxval minexclude maxexclude

For example:

5::10 minexclude maxexclude

  • Both minval and maxval are excluded for any query operation. In the example, it considers the value of the range from 6 to 9 (excluding 5 and 10).
  • The selectables includeminval and includemaxval both return FALSE.
::maxval [|maxexclude]

For example:

::10

  • The value of the range is considered from the negative system limit for integer or float values (e.g., from -2,147,483,648 to +10).
  • The selectable openminval returns TRUE.
minval:: [|minexclude]

For example:

5::

  • The value of the range is considered from minval up to the positive system limit for integer or float values.
  • The selectable openmaxval returns TRUE.

If a business object needs the range-value attribute to be open-ended for the minimum or maximum values, then that value does not need to be provided.

The following table shows some examples of adding and modifying range-value attributes for a business object.

MQL Command Description
add bus T N R intattr 1::3 minexclude maxexclude; The attribute intattr is stored in the database as two separate table rows with values 1 and 3, and orders 1 and 2, respectively.
add bus T N R intattr ::3; The minval is open in this case.
add bus T N R intattr 3::; The maxval is open in this case.
mod bus T N R intattr add 4::5; Multiple values are not allowed for range-value attributes. Since the attribute already has a range of 1::3, attempting to add a second range will throw an error.
mod bus T N R intattr 4::5; This range will replace the existing range value of 1::3 with the range value of 4::5.

The following example uses a combination of single-value, multi-value, and range-value attributes with other business objects in a single MQL command:

mod bus T N R singleattr 2 multiattr test1,test2,test3
 rangeattr 1::5 policy p multiattr add test4;

The above command has the following effect:

  1. The single-value attribute named singleattr is assigned the value 2.
  2. The multi-value attribute named multiattr is assigned the values test1, test2, test3.
  3. The range-value attribute named rangeattr is assigned the range 1::5.
  4. The policy p is assigned to the business object.
  5. A fourth value of test4 is added to the multi-value attribute named multiattr.

Adding and Removing Values from Multi-Value Attributes

You can remove a value from a multi-value attribute, for example, as follows:

mod bus T N R ATTR_NAME remove 3;

The above command removes the value 3 from the multi-value attribute on the business object. If there are multiple rows with the same value, then all of those rows are removed.

A multi-value attribute can have more than one instance of the same value. The command add bus T N R intattr 1,2,3,1; will create four separate rows in the database table.

The following table shows some examples of adding/modifying/removing multi-value attributes for a business object. The same applies to attributes for relationships. In these examples, intattr is an integer, multi-valued attribute. The order values in the database are 1-based.

add bus T N R intattr 1,2,3; Attribute values 1,2,3 are added in that order.
mod bus T N R intattr add 4 order 2; Attribute value 4 is inserted in the third position, so that the values are 1,2,4,3.
mod bus T N R intattr add 8; Attribute value 8 is added in the last position, so that the values become 1,2,4,3,8.
mod bus T N R intattr remove 4; The value 4 is removed from the attribute. If there are several instances of the same value, all are removed.
mod bus T N R intattr remove order 2; The value in the third position is removed.

mod bus T N R intattr replace 5 order 2;

The current value in the third position is replaced with the value 5.
mod bus T N R intattr 7; The attribute value 7 replaces all other values, and the attribute value for the object becomes only 7.

Querying a Business Object for Multi-Value or Range-Value Attributes

Printing a business object returns multiple values for a multi-value attribute, in ascending order. For example, if there exists a type T1 with an integer multi-value attribute M1 and there is one object of this type, printing this object produces the following results:

add bus T1 test 0 policy P1 M1 1,2,3; 
print bus T N R select attribute[M1].value; 
   attribute[M1].value = 1 
   attribute[M1].value = 2 
   attribute[M1].value = 3

There is no selectable that can retrieve all of the values of a multi-value attribute as a single string.

For range-value attributes, the existing value selectable returns two values, as shown below:

add bus T1 test 0 policy P1 M1 1::3; 
print bus T N R select attribute[M1].value; 
   attribute[M1].value = 1 
   attribute[M1].value = 3  

The minval and maxval selectables for business objects print the minimum and maximum values, respectively, of range-value attributes. For example:

print bus T N R select attribute[NAME].minval; Returns the minimum value of a range-value attribute. Returns nothing for multi-value and single-value attributes.
print bus T N R select attribute[NAME].maxval; Returns the maximum value of a range-value attribute. Returns nothing for multi-value and single-value attributes.
print bus T N R select attribute[NAME].size; Returns 2, since there are two instances of a range-value attribute on the business object.
Using the minvaland maxvalselectables in query Where clauses may have performance issues. It is recommended not to use either of these selectables as part of Where clauses.

Given a business object with a multi-value attribute M1 created with the command:

add bus T1 test 0 policy P1 M1 "1","2","3";

The following table lists the outputs produced by various queries of this business object:

Query Returns:
temp quer bus T1 * * where attribute[M1].value >= 1; T1 test 0
temp quer bus T1 * * where attribute[M1].value == 1; T1 test 0
temp quer bus T1 * * where "attribute[M1].value == 1 || attribute[M1].value == 2"; T1 test 0
temp quer bus T1 * * where attribute[M1].value > 3; Nothing

Given a business object with a range-value attribute M1 created with the command:

add bus T1 test 0 policy P1 M1 1:3;

The results from greater-than '>' and less-than '<' operators for range-value attributes are interpreted such that the entire range for the attribute should be '>' or '<' the literal.

The following table lists the outputs produced by various queries of this business object:

Query Returns
temp quer bus T1 * * where attribute[M1].value >= 1; T1 test 0

Both the minval and the maxval are >= 1.

temp quer bus T1 * * where attribute[M1].value >= 1; T1 test 0

Minval is == 1.

temp quer bus T1 * * where "attribute[M1].value == 1 | | attribute[M1].value == 2"; T1 test 0
temp quer but T1 * * where attribute[M1].value > 0; T1 test 0

Both minval and maxval are > 0.

temp quer bus T1 * * where attribute[M1].value > 3; Nothing

Both minval and maxval are <= 3.

temp quer bus T1 * * where attribute[M1].value < 2; Nothing

Maxval > 2.

Given a business object with a multi-value attribute M1 created with the commands:

add bus T1 test 0 policy P1 M1 1,2,3; 
add bus T1 test2 0 policy P1 M1 4,5,6; 
add bus T1 test3 0 policy P1 M1 7, 2,3;

The following table lists the outputs produced by various queries of this business object:

Query Returns:
temp quer bus T1 * * where attribute[M1].value >= 1; T1 test 0

T1 test2 0

T1 test3 0

T1 test 0

temp quer bus T1 * * where attribute[M1].value == 1; T1 test 0
temp quer bus T1 * * where attribute[M1].value != 1; T1 test 0

T1 test2 0

T1 test3 0

temp quer bus T1 * * where attribute[M1].value > 3; T1 test2 0

T1 test3 0

Given a business object with a multi-value attribute M1 created with the commands:

add bus T1 test 0 policy P1 M1str val1,val2,val3;
add bus T1 test2 0 policy P1 M1 val4,val5,val6;  
add bus T1 test3 0 policy P1 M1str Val1,val2,val3;

The following table lists the outputs produced by various queries of this business object:

Query Returns:
temp quer bus T1 * * where attribute[M1].value == val1; T1 test 0
temp quer bus T1 * * where attribute[M1].value != val1; T1 test 0

T1 test2 0

T1 test3 0

All three objects have values other than "val1".

temp query bus T1 * * where attribute[M1].value match val1; T1 test 0

This is a case-sensitive match.

temp query bus T1 * * where attribute[M1].value nmatch val1; T1 test 0

T1 test2 0

T1 test3 0

This is a case-sensitive not-match.

temp query bus T1 * * where attribute[M1].value smatch val1; T1 test 0

T1 test3 0

This is a case-insensitive match. "Val1" is equal to "val1" when the comparison is case-insensitive.

temp query bus T1 * * where attribute[M1].value nsmatch 1; T1 test 0

T1 test2 0

T1 test3 0

All three objects have values other than "val1".

In the case of multi-value attributes, using ".value" in the Where clause (for example, where attribute[M1].value == 'val1' ) is less efficient than without (for example, where attribute[M1] == 'val1' ). This is because the Where clause condition is resolved by a precise select statement, and when ".value" is not used, evaluation is done in memory, which is more intensive. It is, therefore, advisable to construct Where clauses without ".value".

Expressions with Multi-Value Selectables

Expressions with multi-value selectables in the Where clause maintain the data type of the underlying data. In cases where there are multiple expressions involving the same attribute (for example, where [(attribute[M1] == val1) && (attribute[M1] == valN) .. ], only the first expression (attribute[M1] == val1) is SQL'ized, and the rest are resolved in memory.

In Where Used queries, it is prohibited to use multi-value or range-value attributes. The Orderby clause is also not allowed if multi-value or range-value attributes are used in a query.

In the case of range-value attributes, some operators (mainly the ones dealing with strings and patterns such as match, nmatch, smatch, and so on) do not produce accurate results. They treat the value [|(minval::maxval)|] as a string and make a comparison against it.

Dimensions and Multi-Value or Range-Value Attributes

Dimensions can be added for multi-value attributes, as is currently possible in the system. For more information, see Dimensions). Only one dimension is allowed per attribute type, whether multi- or single-value. However, for multi-value attributes, every single value can have its own UOM when a dimension is applied to the attribute type (i.e., each attribute value can have its own UOM value). There is a one-to-one correspondence between the entries in the attribute table and in the unit table. For example:

add dimension d; 
mod dimension d add unit km label kilometers unitdescription  kilometer_desc multiplier 1000
 kilometer_desc multiplier 1000 offset 0 setting METRIC true;; add attribute M1 type integer
add attribute M1 type integer dimension d multival true; 
add attribute R1 type integer dimension d rangeval true; 
add type T1 attribute M1,R1; 
add bus T1 N1 0 M1 "100km","200km","300km" R1 "10 km::100 km";

Since the attribute M1 has three values, the above add bus statement should see three separate entries for the UOM values in the unit table and three corresponding values in the attribute table in the database. The entries in the two tables are tied together with the order number.

The following attribute selectables return multiple values, all of which are output based on the order number:

attribute.inputvalue;
attribute.inputunit;
attribute.dbvalue;
attribute.dbunit;
attribute.unitvalue;
attribute.generic;

For range-value attributes, there is just one UOM value for the entire range in the unit table.

History and Multi-Value or Range-Value Attributes

The history entry for a multi-value attribute is delimited by a comma and truncated to 255 characters maximum length. If a single attribute setting sets the attribute to multiple values, which concatenates the values delimited by ',' and generates a string that is longer than 255 characters, only the first 255 characters of the attribute value are stored in the history tables in the database.

The history entry for the attribute modifications also includes the existing value of the attribute, and the same 255 character limitation applies to the existing attribute values.

For a multi-value attribute, an example of a history entry would be:

history = modify - user: creator time: Fri Jul 20, 2012 11:00:54 AM 
   EDT state: s1 attr: 1,2,3,[..up to 255 chars] was 20,30,40[..up to 
   255 chars]

For a range-value attribute, the range is specified. An example of a history entry would be:

history = modify - user: creator time: Fri Jul 20, 2012 11:00:54 AM 
   EDT state: s1 attr: 20::30 was 10::20

Triggers and Multi-Value or Range-Value Attributes

The ATTRTYPEKIND macro specifies whether an attribute is single-value, multi-value, or range-value, respectively, by having one of these values:

  • Single
  • Multi
  • Range

You can use the NEWATTRVALUE macro to enter new multi-value and range-value attribute values delimited by "^G" (the beep character). The trigger would then have to parse the string to get the multiple values for such attributes.

You can use the ATTRVALUE macro to enter current multi-value and range-value attribute values, again delimited by "^G" (the beep character). The trigger would then have to parse the string to get the multiple values for such attributes.

Unique Keys or Indexes and Multi-Value or Range-Value Attributes

Unique keys and indexes are not supported for multi-value or range-value attributes. This means that:

  • If a multi-value or range-value attribute is used as a field while defining an index or unique key, an error will be thrown.
  • If there is an existing unique key or index that has a single-value attribute and you try to modify that attribute to become a multi-value or range-value attribute, an error will be thrown.

Adaplets and Multi-Value or Range-Value Attributes

Adaplets do not support multi-value or range-value attributes. This means that:

  • If you modify an existing attribute to become a multi-value or range-value attribute, the first time that the attribute vault is loaded after the change, an error will be thrown.
  • If any new attributes are added that are multi-value or range-value attributes and they are used in an adaplet mapping file, again an error will be thrown.