company logo

Transient attribute extensions

Transient attribute extensions allow creating new attributes for a property handle at run-time. One may create any kind of attribute, but no references or relationships. Attribute extensions are not created for an instance, but for a property handle, i.e. those are available for all instances managed by the property handle.

In contrast to persistent attribute extensions (property extension), transient attribute extensions are not limited in size. One may also define expandable string attributes with unlimited size.

Extension attributes may be defined as static or non-static attributes. Static extension attributes are always accessible and do not change value when selection changes in the parent property handle. Non-static extension attributes are accessible only, when the parent property handle is selected. Usually, non-static attribute extensions change its value, when the parent property's selection changes.

One may define the value for an extension attribute by setting a data source. When accessing an extension attribute with a data source expression, the expression is evaluated when creating or accessing the attribute. For static extension attributes the value is calculated ones when creating the attribute. Non-static extension attributes evaluate the data source expression always after the selection in the property handle changes and the extension attribute is accessed.

When creating cursor copies ( Property ::cursorCopy() ), attribute extensions are copied to the property handle copy, but not maintained simultaneously, i.e. creating or removing extension attributes from one of the property handles will not affect the other one.

Notes:

When referring to extension properties, those are added automatically to the list of attribute extensions, i.e. besides the list of attribute extensions explicitly created, the list also contains all extension properties accessed in the context of the property handle.

Create and remove attribute extensions

In order to create attribute extensions, one may call Property ::createAttributeExtension() . The function receives a string with an ODL attribute definition. Typically, an expression is defined for assigning a value to the attribute. When no value has been assigned, the attribute value has to be set by the application.

Attribute extensions created ones may be removed from the property handle when not being used anymore by calling ( Property ::removeAttributeExtension() with the name of the extension attribute to be removed.

In order to define static extension attributes, the static . keyword has to precede the attribute definition.

Extension attributes may refer to a re-sizable instance area. When defining text attributes ( STRING ) without size definition, an expandable attribute is created, which expands the text area to the requested size when being updated.

Besides type specifications, parameter definitions also may contain several extended options.

// instance depending

  createAttributeExtension('int age = (Date()-birth_date)/365');

// static attribute extension

  createAttributeExtension('static int sum_age');

// fixed string extension

  createAttributeExtension('string(50) my_name = name + "," + first_name);

// extendable string extension

  createAttributeExtension('static string all_names');

Notes:

When the data type is extendable (i.e. it contains a reference collection __EXTENSIONS ), names for attribute extensions must not be defined in the extension schema in the database or dictionary, since all properties defined in the extension schema are considered as potential properties of any extendable data type.

Extended options

In general, one may add extended options to a variable (parameter) definition. Extended options are used in specific context only, i.e. it depends on the function or operation that refers to the parameter, whether it accepts or ignores the options. Typical example for using extended options is Property ::orderBy() .

When evaluating the variable or parameter definitions, option values are transferred to value definition (property definition) and can be checked by the called function:

  • IGNORE_CASE : PropertyDefinition ::ignoreCase()
  • DESCENDING : PropertyDefinition ::descendingOrder()
  • UNIQUE : PropertyDefinition ::isUniqueCollection()
  • NOT_EMPTY : PropertyDefinition ::supressEmpty()
  • STATIC : PropertyDefinition ::isStatic()

By checking the parameters passed one may obtain information about additional option settings.

When passing extension attributes to OSI functions (as orderBy() ) or referring to it in OSI statements, parameter options set for an extension attribute are passed to the function, i.e. defining DESCENDING for an extension attribute passed to orderBy() as sort column will cause ordering the column values descending.

Accessing attribute extensions

In order to access attribute extensions, one may use the Property ::value() function. Since attribute extensions are not part of the schema, one cannot access extension attributes directly by name in an OSI expression. When an extension attribute has been defined as non-static attribute, it is accessible, only, when the property handle is selected. Static extension attributes are accessible at any time.

In order to access an extension attribute explicitly, one may also call Property ::attributeExtension() . The function also returns a value handle for the attribute extension but fails, when the attribute has not been created as attribute extension. More important, however, is that calling this function prevents programmers from looking for extension attributes in the database schema.

When a data source (expression) had been defined (for a non-static attribute), the extension attribute (value) is evaluated automatically for each selected instance. When not defining a data source for a static attribute extension, the data source should not depend on instance selection. Static extension attributes are evaluated only once, when creating the attribute. They may, however, be updated by the application (as sum_age in the example below)..

When accessing non-static attribute extension and no instance is selected in the owning property handle, an exception will be thrown.

void Person::AvarageAge() {

  createAttributeExtension("static int sum_age");

  createAttributeExtension("static int pcount = count");

  Message(value("pcount"));

  top;

  while ( next )

    value("sum_age") += age;

  Message(value("sum_age")/value("pcount"));

  

  removeAttributeExtension("sum_age");

  removeAttributeExtension("pcount");

}

Notes:

In contrast to local variables, attribute extensions created in a function persist after leaving the function. In order to increase transparency, it is suggested removing attribute extensions as soon as not needed anymore.

Manage attribute extensions

In order to check existing attribute extensions, one may call attributeExtensionsCount() or attributeExtensionExist() .

In order to avoid exceptions, one may check by calling Property ::attributeExtensionExist() passing the attribute name, whether an extension attribute exists or not. For listing defined attribute extensions, one should call attributeExtensionsCount() for avoiding exceptions.

Attribute extensions created once may be removed by calling removeAttributeExtension() . When removing attribute extensions from a original property handle, for which one or more cursor copies had been created, copies for those attribute extensions, which had been passed to the cursor property handle when being created, will still exist. .

// list attribute extension values

  num = attributeExtensionsCount();

  while ( --num >= 0 )

    Message( attributeExtension(num) );

// check attribute extension value

  if ( attributeExtensionExist("age_sum") )

    Message( attributeExtension("age_sum") );  

Extension attributes created implicitly

In some cases, extension attributes are created implicitly. Typically, attributes defined in an orderBy() , select() or other OQL operations cause creating attribute extensions for newly created attributes. In many cases, values defined as attribute declaration in the function parameter will be created as attribute extension for the calling property handle.

// creates attribute extension agegroup for person

person.orderBy("string age_group = (age < 20 ? 'young' :

                                    age < 50 ? 'middle':

                                               'old'    ),sex");