Skip to main content

Defining and Using Literal Properties

You can define literal properties in any object class. A literal property holds a literal value and is based on a data type class. This topic describes how to define and use such properties.

Where noted, some topics also apply to properties of other kinds.

Defining Literal Properties

To add a literal property to a class definition, add an element like one of the following to the class:

Property PropName as Classname;
Property PropName as Classname [ Keywords ] ;
Property PropName as Classname(PARAM1=value,PARAM2=value) [ Keywords ] ;
Property PropName as Classname(PARAM1=value,PARAM2=value) ;

Where:

  • PropName is the name of the property.

  • Classname is the class on which this property is based. If you omit this, Classname is assumed to be %StringOpens in a new tab. To define this property as a literal property, either omit Classname or specify Classname as the name of a data type class; see Common Data Type Classes. You could also use a custom data type class.

  • Keywords represents any property keywords. See Compiler Keywords.

  • PARAM1, PARAM2, and so on are property parameters. The available parameter depend on the class used by the property.

Notice that the property parameters, if included, are enclosed in parentheses and precede any property keywords. The property keywords, if included, are enclosed in square brackets.

Examples

For example, a class can define a Count property using the %IntegerOpens in a new tab data type class:

Property Count As %Integer;

Because %IntegerOpens in a new tab is a data type class, Count is a data type property.

You can use data type parameters to place constraints on the allowed values of data type properties. For example, for a property of type %IntegerOpens in a new tab, you can specify the MAXVAL parameter:

Property Count As %Integer(MAXVAL = 100);

To set a data type property value equal to the empty string, use code of the form:

 Set object.Property = $C(0)

Every property has a collation type, which determines how values are ordered (such as whether capitalization has effects or not). The default collation type for strings is SQLUPPER. For more details on collations, see Data Collation.

Defining an Initial Expression for a Property

By default, when a new object is created, each property equals null. You can specify an ObjectScript expression to use as the initial value for a given property instead. The expression is evaluated when the object is created.

To specify an initial expression for a property, include the InitialExpression keyword in the property definition:

Property PropName as Classname [ InitialExpression=expression ] ;

Where expression is an ObjectScript expression (note that you cannot use any other language for this expression). For details, see InitialExpression.

Defining a Property As Required

This option applies only to properties in persistent classes. (Note that this option applies to any kind of property, not just literal ones.)

By default, when a new object is saved, InterSystems IRIS does not require it to have non-null values for its properties. You can define a property so that a non-null value is required. To do so, include the Required keyword in the property definition:

Property PropName as Classname [ Required ] ;

Then, if you attempt to save an object that has a null value for the property, InterSystems IRIS issues the following error:

ERROR #5659: Property required

The Required keyword also affects how you can insert or modify data for this class via SQL access. Specifically, an error occurs if the value is missing when you attempt to insert or update a record.

Defining a Computed Property

In InterSystems IRIS, you can define computed properties, whose values are computed via ObjectScript, possibly based on other properties. The generic phrase computed properties (or computed fields) includes both of the following variations:

  • Always computed — The value of this property is calculated when it is accessed. It is not stored in the database unless you defined an index, in which case that index is stored.

  • Triggered computed — The value of this property is recalculated when triggered (details given below).

    If the property is defined in a persistent class, its value is stored in the database.

In both cases, the recalculation is performed whether you use object access or an SQL query.

There are five property keywords (SqlComputed, SqlComputeCode, SqlComputeOnChange, Transient, Calculated) that control if and how a property is computed. Instead of specifying SqlComputeCode, you can write compute code in a PropertyComputation method, where Property is the name of the computed property. For more details, see Computed Values.

The following table summarizes the possibilities:

How to Tell if a Property Is Computed
    SqlComputed is true (and SqlComputeCode is defined) SqlComputed is false
Calculated is true Transient is true Property is always computed Property is not computed
Calculated is true Transient is false Property is always computed Property is not computed
Calculated is false Transient is true Property is always computed Property is not computed
Calculated is false Transient is false Property is triggered computed (SqlComputeOnChange can also be specified in this case) Property is not computed

To define a computed property, do the following:

  • Include the SqlComputed keyword in the property definition. (That is, specify the SqlComputed keyword as true.)

  • Include the SqlComputeCode keyword in the property definition. For the value of this keyword, specify (in curly braces) a line of ObjectScript code that sets the value of the property, according to rules given in SqlComputeCode. For example:

    Class Sample.Population Extends %Persistent
    {
    Property FirstName As %String;
    
    Property LastName As %String;
    
    Property FullName As %String [ SqlComputeCode = {set {*}={FirstName}_" "_{LastName}}, SqlComputed ];
    // ...
    
    }
    

    Alternatively, specify a PropertyComputation method using ObjectScript or another language, such as Python, to set the value of the property. For example:

    Class Sample.Population Extends %Persistent
    {
    Property FirstName As %String;
    
    Property LastName As %String;
    
    Property FullName As %String [ SqlComputed ];
    // ...
    
    ClassMethod FullNameComputation(cols As %Library.PropertyHelper) As %String
    {
        return cols.getfield("FirstName")_" "_cols.getfield("LastName")
    }
    // ...
    }
    
    Class Sample.Population Extends %Persistent
    {
    Property FirstName As %String;
    
    Property LastName As %String;
    
    Property FullName As %String [ SqlComputed ];
    // ...
    
    ClassMethod FullNameComputation(cols As %Library.PropertyHelper) As %String [ Language = python ]
    {
        return cols.getfield("FirstName") + " " + cols.getfield("LastName")
    }
    // ...
    }
    
  • If you want to make the property always computed, specify the Calculated keyword as true in the property definition.

    Or, if you want to make the property triggered computed, do not include the Calculated and Transient keywords in the property definition. (That is, make sure both keywords are false.)

  • If the property is triggered computed, optionally specify SqlComputeOnChange.

    This keyword can specify one or more properties. When any of these properties change in value, the triggered property is recomputed. Note that you must use the property names rather than the names given by SqlFieldName, which is discussed later). For example (with artificial line breaks):

    Property messageId As %Integer [ 
    SqlComputeCode = { set {*}=$Select({Status}="":0,1:$List($List($Extract({Status},3,$Length({Status}))))) }, 
    SqlComputed, SqlComputeOnChange = Status ];
    

    For another example (with artificial line breaks):

    Property Test2 As %String [ SqlComputeCode = { set {*}={Refprop1}_{Refprop2}}, SqlComputed, 
    SqlComputeOnChange = (Refprop1, Refprop2) ];
    

    The value of SqlComputeOnChange can also include the values %%INSERT or %%UPDATE; for details, see SqlComputeOnChange.

If you intend to index this field, use deterministic codeOpens in a new tab, rather than nondeterministic code. InterSystems IRIS cannot maintain an index on the results of nondeterministic code because it is not possible to reliably remove stale index key values. (Deterministic code returns the same value every time when passed the same arguments. So for example, code that returns $h is nondeterministic, because $h is modified outside of the control of the function.)

Also see Calculated. And see Controlling the SQL Projection of Computed Properties, below.

Defining a Multidimensional Property

You can define a property to be multidimensional, which means that you intend the property to act as a multidimensional array. To do so, include the MultiDimensional keyword in the property definition:

Property PropName as Classname [ MultiDimensional ] ;

This property is different from other properties as follows:

  • InterSystems IRIS does not provide property methods for it (see Using and Overriding Property Methods).

  • It is ignored when the object is validated or saved.

  • It is not saved to disk, unless your application includes code to save it specifically.

  • It cannot be exposed to clients such as Java.

  • It cannot be stored in or exposed through SQL tables.

Multidimensional properties are rare but provide a useful way to temporarily contain information about the state of an object.

Also see Specifying Values for a Multidimensional Property.

Defining Enumerated Properties

Many properties support the parameters VALUELIST and DISPLAYLIST. You use these to define enumerated properties.

To specify a list of valid values for a property, use its VALUELIST parameter. The form of VALUELIST is a delimiter-separated list of logical values, where the delimiter is the first character. For instance:

Property Color As %String(VALUELIST = ",red,green,blue");

In this example, VALUELIST specifies that valid possible values are red, green, and blue, with a comma as its delimiter. Similarly,

Property Color As %String(VALUELIST = " red green blue");

specifies the same list, but with a space as its delimiter.

The property is restricted to values in the list, and the data type validation code simply checks to see if the value is in the list. If no list is present, there are no special restrictions on values.

DISPLAYLIST is an additional list that, if present, represents the corresponding display values to be returned by the LogicalToDisplay() method of the property.

For an example that shows how to obtain the display values, see Using Property Methods.

Specifying Values for Literal Properties

To specify a value for a literal property, use the SET command, an OREF, and dot syntax as follows:

 SET oref.MyProp=value

Where oref is an OREF, MyProp is a property of the corresponding object, and value is an ObjectScript expression that evaluates to a literal value. For example:

 SET patient.LastName="Muggles"
 SET patient.HomeAddress.City="Carver"
 SET mrn=##class(MyApp.MyClass).GetNewMRN()
 set patient.MRN=mrn

The literal value must be a valid logical value for the property type. For example, use 1 or 0 for a property based on %BooleanOpens in a new tab. For another example, for an enumerated property, the value must be one of the items specified by the VALUELIST parameter.

Specifying Values for a Multidimensional Property

For a multidimensional property, you can specify values for any subscripts of the property. For example:

 set oref.MyStateProp("temp1")=value1
 set oref.MyStateProp("temp2")=value2
 set oref.MyStateProp("temp3")=value3

Multidimensional properties are useful for holding temporary information for use by the object. These properties are not saved to disk.

Using Property Methods

Each property adds a set of generated class methods to the class. These methods include propnameIsValid(), propnameLogicalToDisplay(), propnameDisplayToLogical(), propnameLogicalToOdbc(), propnameOdbcToLogical(), and others, where propname is the property name. Some of these methods are inherited from the %Property class and others are inherited from the data type class on which the property is based. For details and a list of the methods, see Defining Data Type Classes.

InterSystems IRIS uses these methods internally, and you can call them directly as well. In each case, the argument is a property value. For example, suppose that Sample.Person had a property named Gender with logical values M and F (and display values Male and Female). You could display the logical and display values for this property for a given record, as follows;

MYNAMESPACE>set p=##class(Sample.Person).%OpenId(1)
 
MYNAMESPACE>w p.Gender
M
MYNAMESPACE>w ##class(Sample.Person).GenderLogicalToDisplay(p.Gender)
Male

Controlling the SQL Projection of Literal Properties

A persistent class is projected as an SQL table. For that class, all properties are projected to SQL, aside from the following exceptions:

This section discusses the details for literal properties.

Specifying the Field Names

By default, a property (if projected to SQL) is projected as an SQL field with the same name as the property. To specify a different field name, use the property keyword SqlFieldName. (You may want to use this keyword if the property name is an SQL reserved word). For instance, if there is a %StringOpens in a new tab property called “Select,” you could define its projected name with the following syntax:

Property Select As %String [ SqlFieldName = SelectField ];
Note:

If you do use a property name that is an SQL reserved word, you can also escape the corresponding field name with double quotes when using it in a SQL statement, for example:

SELECT ID, Name, "Select" FROM SQLUser.Person

For more information, see Delimited Identifiers.

Specifying the Column Numbers

The system automatically assigns a unique column number for each field. To control column number assignments, specify the property keyword SqlColumnNumber, as in the following example:

Property RGBValue As %String [ SqlColumnNumber = 3 ];

The value you specify for SqlColumnNumber must be an integer greater than 1. If you use the SqlColumnNumber keyword without an argument, InterSystems IRIS assigns a column number that is not preserved and that has no permanent position in the table.

If any property has an SQL column number specified, then InterSystems IRIS assigns column numbers for the other properties. The starting value for the assigned column numbers is the number following the highest SQL column number specified.

The value of the SqlColumnNumber keyword is inherited.

Effect of the Data Type Class and Property Parameters

The data type class used by a given property has an effect on the SQL projection. Specifically, the SQL category of the data type (defined with the SqlCategory keyword) control how the property is projected. Where applicable, the property parameters also have an effect:

For example, consider the following property definition:

Property Name As %String(MAXLEN = 30);

This property is projected as a string field with a maximum length of 30 characters.

Controlling the SQL Projection of Computed Properties

In InterSystems IRIS, you can define computed properties, whose values are computed via ObjectScript; see Defining Computed Properties. The following table indicates which variations are projected to SQL:

Property Definition Projection to SQL
Property is not computed and is not transient (the default) Property is projected to SQL
Property is not computed and is transient Property is not projected to SQL
Property is always computed Property is projected to SQL
Property is triggered computed Property is projected to SQL

This table considers only the effects of the Calculated, Transient, SqlComputed, and SqlComputeCode keywords. It assumes that the property does not use other keywords that would prevent it from having an SQL projection. For example, it assumes that the property is not private.

See Also

FeedbackOpens in a new tab